index.vue 65 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816
  1. <template>
  2. <div class="app-container">
  3. <el-row :gutter="20">
  4. <!--部门数据-->
  5. <el-col :span="2" :xs="24">
  6. <div class="head-container">
  7. <el-input v-model="deptName" placeholder="请输入部门名称" clearable size="small" prefix-icon="el-icon-search" style="margin-bottom: 20px" />
  8. </div>
  9. <div class="head-container">
  10. <el-tree :data="deptOptions" :props="defaultProps" :expand-on-click-node="false" :filter-node-method="filterNode" ref="tree" @node-click="handleNodeClick" />
  11. </div>
  12. </el-col>
  13. <!--用户数据-->
  14. <el-col :span="22" :xs="24">
  15. <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="100px">
  16. <el-form-item label="ID" prop="userId">
  17. <el-input v-model="queryParams.userId" placeholder="请输入员工ID" clearable size="small" style="width: 240px" @keyup.enter.native="handleQuery" />
  18. </el-form-item>
  19. <el-form-item label="员工后台昵称" prop="nickName">
  20. <el-input v-model="queryParams.nickName" placeholder="请输入员工后台昵称" clearable size="small" style="width: 240px" @keyup.enter.native="handleQuery" />
  21. </el-form-item>
  22. <el-form-item label="手机号码" prop="phonenumber">
  23. <el-input v-model="queryParams.phonenumber" placeholder="请输入手机号码" clearable size="small" style="width: 240px" @keyup.enter.native="handleQuery" />
  24. </el-form-item>
  25. <el-form-item label="状态" prop="status">
  26. <el-select v-model="queryParams.status" placeholder="员工状态" clearable size="small" style="width: 240px" @change="handleQuery">
  27. <el-option v-for="dict in statusOptions" :key="dict.dictValue" :label="dict.dictLabel" :value="dict.dictValue" />
  28. </el-select>
  29. </el-form-item>
  30. <el-form-item label="企微状态" prop="qwStatus">
  31. <el-select v-model="queryParams.qwStatus" placeholder="企微绑定状态" clearable size="small" style="width: 240px" @change="handleQuery">
  32. <el-option v-for="dict in qwStatusOptions" :key="dict.dictValue" :label="dict.dictLabel" :value="dict.dictValue" />
  33. </el-select>
  34. </el-form-item>
  35. <el-form-item label="创建时间">
  36. <el-date-picker v-model="dateRange" size="small" style="width: 240px" value-format="yyyy-MM-dd" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
  37. </el-form-item>
  38. <el-form-item>
  39. <el-button icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
  40. <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
  41. </el-form-item>
  42. </el-form>
  43. <el-row :gutter="10" class="mb8">
  44. <el-col :span="1.5">
  45. <el-button plain type="primary" icon="el-icon-plus" size="mini" @click="handleAdd" v-hasPermi="['company:user:add']">新增</el-button>
  46. </el-col>
  47. <el-col :span="1.5">
  48. <el-button plain type="success" icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate" v-hasPermi="['company:user:edit']">修改</el-button>
  49. </el-col>
  50. <el-col :span="1.5">
  51. <el-button plain type="success" icon="el-icon-edit" size="mini" :disabled="multiple" @click="batchEditRole"v-hasPermi="['company:user:edit']">批量修改角色</el-button>
  52. </el-col>
  53. <el-col :span="1.5">
  54. <el-button plain type="danger" icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete" v-hasPermi="['company:user:remove']">删除</el-button>
  55. </el-col>
  56. <el-col :span="1.5">
  57. <el-button plain type="info" icon="el-icon-upload2" size="mini" @click="handleImport" v-hasPermi="['company:user:import']">导入</el-button>
  58. </el-col>
  59. <el-col :span="1.5">
  60. <el-button plain type="warning" icon="el-icon-download" size="mini" @click="handleExport" v-hasPermi="['company:user:export']">导出</el-button>
  61. </el-col>
  62. <el-col :span="1.5">
  63. <el-button
  64. type="primary"
  65. plain
  66. size="mini"
  67. @click="synOpen=true"
  68. v-hasPermi="['qw:user:sync']"
  69. >同步企微员工和部门</el-button>
  70. </el-col>
  71. <el-col :span="1.5">
  72. <el-button
  73. type="primary"
  74. plain
  75. size="mini"
  76. @click="synNameOpen=true"
  77. v-hasPermi="['qw:user:sync']"
  78. >同步企微员工名称</el-button>
  79. </el-col>
  80. <el-col :span="1.5">
  81. <el-button
  82. type="primary"
  83. plain
  84. size="mini"
  85. :disabled="multiple"
  86. @click="handerCompanyUserAreaList"
  87. >批量设置销售所属区域</el-button>
  88. </el-col>
  89. <el-col :span="1.5">
  90. <el-button
  91. type="primary"
  92. plain
  93. size="mini"
  94. :disabled="multiple"
  95. @click="handleSetRegister"
  96. >设置单独注册会员</el-button>
  97. </el-col>
  98. <el-col :span="1.5">
  99. <el-button
  100. type="primary"
  101. plain
  102. size="mini"
  103. :disabled="multiple"
  104. @click="handleAllowedAllRegister"
  105. >允许注册会员开关</el-button>
  106. </el-col>
  107. <el-col :span="1.5">
  108. <el-button
  109. type="primary"
  110. plain
  111. size="mini"
  112. @click="handleBindCompanyUserCode"
  113. >生成注册/绑定销售二维码</el-button>
  114. </el-col>
  115. <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
  116. </el-row>
  117. <el-table height="500" border v-loading="loading" :data="filteredUserList" @selection-change="handleSelectionChange">
  118. <el-table-column type="selection" width="50" align="center" />
  119. <el-table-column label="ID" align="center" prop="userId" :show-overflow-tooltip="true" />
  120. <el-table-column label="员工后台账号" align="center" prop="userName" :show-overflow-tooltip="true" width="100" />
  121. <el-table-column label="员工后台昵称" align="center" prop="nickName" :show-overflow-tooltip="true" 员工后台 width="100"/>
  122. <el-table-column label="部门" align="center" prop="deptName" :show-overflow-tooltip="true" />
  123. <el-table-column label="手机号码" align="center" prop="phonenumber" width="120" />
  124. <el-table-column label="账户角色" align="center" :show-overflow-tooltip="true" width="150">
  125. <template slot-scope="scope">
  126. <span v-if="scope.row.roleNames && scope.row.roleNames.length > 0">
  127. {{ scope.row.roleNames.join('、') }}
  128. </span>
  129. <span v-else>-</span>
  130. </template>
  131. </el-table-column>
  132. <el-table-column label="二维码" align="center" prop="qrCodeWeixin">
  133. <template slot-scope="scope">
  134. <!-- 显示已上传的二维码 -->
  135. <el-image
  136. v-if="scope.row.qrCodeWeixin"
  137. style="width: 80px; height: 80px; margin-bottom: 5px; display: block; margin-left: auto; margin-right: auto;"
  138. :src="scope.row.qrCodeWeixin"
  139. :preview-src-list="[scope.row.qrCodeWeixin]"
  140. fit="contain">
  141. <div slot="error" class="image-slot">
  142. <i class="el-icon-picture-outline"></i>
  143. </div>
  144. </el-image>
  145. <!-- 上传组件 -->
  146. <el-upload
  147. class="avatar-uploader"
  148. action="#"
  149. :show-file-list="false"
  150. :http-request="(options) => handleCustomUpload(options, scope.row)"
  151. :before-upload="(file) => beforeImageUpload(file, scope.row)"
  152. >
  153. <el-button size="small" type="primary" :loading="scope.row.uploading">
  154. {{ scope.row.qrCodeWeixin ? '更换图片' : '上传图片' }}
  155. <i class="el-icon-upload el-icon--right"></i>
  156. </el-button>
  157. </el-upload>
  158. <div v-if="scope.row.uploadError" class="el-upload__tip" style="color: red;">
  159. {{ scope.row.uploadError }}
  160. </div>
  161. </template>
  162. </el-table-column>
  163. <el-table-column label="状态" align="center">
  164. <template slot-scope="scope">
  165. <el-switch v-model="scope.row.status" active-value="0" inactive-value="1" @change="handleStatusChange(scope.row)"></el-switch>
  166. </template>
  167. </el-table-column>
  168. <el-table-column label="企微状态" align="center">
  169. <template slot-scope="scope">
  170. <dict-tag :options="qwStatusOptions" :value="scope.row.qwStatus"/>
  171. </template>
  172. </el-table-column>
  173. <el-table-column label="绑定的企微号" align="center">
  174. <template slot-scope="scope">
  175. <div v-if="scope.row.qwUsers && scope.row.qwUsers.length > 0">
  176. <div v-for="user in scope.row.qwUsers" :key="user.id">
  177. <el-tag size="mini">{{ user.qwUserName }}</el-tag>
  178. </div>
  179. </div>
  180. <div v-else>
  181. <dict-tag :options="qwStatusOptions" :value="scope.row.qwStatus"/>
  182. </div>
  183. </template>
  184. </el-table-column>
  185. <el-table-column label="区域" align="center" prop="addressId">
  186. </el-table-column>
  187. <el-table-column label="创建时间" sortable align="center" prop="createTime" width="160">
  188. <template slot-scope="scope">
  189. <span>{{ parseTime(scope.row.createTime) }}</span>
  190. </template>
  191. </el-table-column>
  192. <el-table-column label="是否单独注册会员" align="center" prop="isNeedRegisterMember" width="80px">
  193. <template slot-scope="scope">
  194. <el-tag
  195. :type="scope.row.isNeedRegisterMember === 1 ? 'success' : 'info'">{{scope.row.isNeedRegisterMember === 1 ? '是' : '否' }}</el-tag>
  196. </template>
  197. </el-table-column>
  198. <el-table-column label="允许注册会员" align="center" prop="isNeedRegisterMember" width="80px">
  199. <template slot-scope="scope">
  200. <el-tag
  201. :type="scope.row.isAllowedAllRegister === 1 ? 'success' : 'info'">{{scope.row.isAllowedAllRegister === 1 ? '是' : '否' }}</el-tag>
  202. </template>
  203. </el-table-column>
  204. <el-table-column label="操作" align="center" width="160" class-name="small-padding fixed-width">
  205. <template slot-scope="scope">
  206. <el-button
  207. size="mini"
  208. type="text"
  209. icon="el-icon-connection"
  210. plain
  211. v-if="scope.row.doctorId!=null"
  212. @click="handleUpdateDoctor(scope.row)"
  213. >换绑医生</el-button>
  214. <el-button
  215. size="mini"
  216. type="text"
  217. plain
  218. icon="el-icon-link"
  219. v-else
  220. @click="handleUpdateDoctor(scope.row)"
  221. >绑定医生</el-button>
  222. <el-button
  223. size="mini"
  224. type="text"
  225. icon="el-icon-unlock"
  226. plain
  227. v-if="scope.row.doctorId!=null"
  228. @click="handleUnBindUserId(scope.row)"
  229. >解绑医生</el-button>
  230. <el-button
  231. v-if="scope.row.qwStatus == 0"
  232. size="mini"
  233. type="text"
  234. icon="el-icon-edit"
  235. @click="qwBind(scope.row)"
  236. v-hasPermi="['qw:user:bind']"
  237. >绑定企微</el-button>
  238. <el-button
  239. v-else
  240. size="mini"
  241. type="text"
  242. icon="el-icon-edit"
  243. @click="qwBind(scope.row)"
  244. v-hasPermi="['qw:user:bind']"
  245. >查或换绑企微</el-button>
  246. <el-button
  247. size="mini"
  248. type="text"
  249. icon="el-icon-user"
  250. plain
  251. @click="handleBindUser(scope.row)"
  252. >绑定用户</el-button>
  253. <el-button v-if="scope.row.userType !== '00'" size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['company:user:edit']">修改</el-button>
  254. <el-button v-if="scope.row.userType !== '00'" size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['company:user:remove']">删除</el-button>
  255. <el-button size="mini" type="text" icon="el-icon-key" @click="handleResetPwd(scope.row)" v-hasPermi="['company:user:resetPwd']">重置密码</el-button>
  256. </template>
  257. </el-table-column>
  258. </el-table>
  259. <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
  260. </el-col>
  261. </el-row>
  262. <!-- 批量修改角色对话框 -->
  263. <el-dialog title="批量修改角色" :visible.sync="batchRoleDialogVisible" width="500px" append-to-body>
  264. <el-form :model="batchRoleForm" label-width="80px">
  265. <el-form-item label="选择角色">
  266. <el-select v-model="selectedRoleIds" multiple placeholder="请选择角色" style="width: 100%;">
  267. <el-option
  268. v-for="item in roleOptions"
  269. :key="item.roleId"
  270. :label="item.roleName"
  271. :value="item.roleId">
  272. </el-option>
  273. </el-select>
  274. </el-form-item>
  275. </el-form>
  276. <div slot="footer" class="dialog-footer">
  277. <el-button @click="batchRoleDialogVisible = false">取 消</el-button>
  278. <el-button type="primary" @click="submitBatchRoles">确 定</el-button>
  279. </div>
  280. </el-dialog>
  281. <!--当点击查或换绑微信时候弹出此框-->
  282. <el-dialog title="绑定企微账号" :visible.sync="qwOpen" width="800px" append-to-body >
  283. <el-form ref="form" :model="form" label-width="80px" >
  284. <el-form-item label="查询" prop="companyUserId">
  285. <el-button type="primary" icon="el-icon-search" @click="selectQwUser()" size="mini">搜索账号</el-button>
  286. </el-form-item>
  287. <el-form-item label="企微账号" prop="companyUserId">
  288. <el-tag
  289. style="margin-left: 5px"
  290. size="medium"
  291. :key="id"
  292. v-for="id in qwUser"
  293. closable
  294. :disable-transitions="false"
  295. @close="handleClosegroupUser(id)">
  296. <span v-for="list in qwUserList" :key="list.qwUserId" v-if="list.id==id">{{list.qwUserName}}({{list.corpName}})
  297. </span>
  298. </el-tag>
  299. </el-form-item>
  300. </el-form>
  301. <div slot="footer" class="dialog-footer">
  302. <el-button type="primary" @click="qwSubmitForm">绑 定</el-button>
  303. <el-button @click="qwCancel">取 消</el-button>
  304. </div>
  305. </el-dialog>
  306. <el-dialog title="选择企微主体" :visible.sync="synOpen" width="800px" append-to-body>
  307. <el-form label-width="80px">
  308. <el-form-item label="企微公司" prop="corpId">
  309. <el-select v-model="synform.corpId" placeholder="企微公司" >
  310. <el-option
  311. v-for="dict in myQwCompanyList"
  312. :key="dict.dictValue"
  313. :label="dict.dictLabel"
  314. :value="dict.dictValue"
  315. />
  316. </el-select>
  317. </el-form-item>
  318. </el-form>
  319. <div slot="footer" class="dialog-footer">
  320. <el-button type="primary" @click="synSubmitForm">确 定</el-button>
  321. <el-button @click="synOpen=false">取 消</el-button>
  322. </div>
  323. </el-dialog>
  324. <el-dialog title="选择企微主体" :visible.sync="synNameOpen" width="800px" append-to-body>
  325. <el-form label-width="80px">
  326. <el-form-item label="企微公司" prop="corpId">
  327. <el-select v-model="synNameform.corpId" placeholder="企微公司" >
  328. <el-option
  329. v-for="dict in myQwCompanyList"
  330. :key="dict.dictValue"
  331. :label="dict.dictLabel"
  332. :value="dict.dictValue"
  333. />
  334. </el-select>
  335. </el-form-item>
  336. </el-form>
  337. <div slot="footer" class="dialog-footer">
  338. <el-button type="primary" @click="synNameSubmitForm">确 定</el-button>
  339. <el-button @click="synNameOpen=false">取 消</el-button>
  340. </div>
  341. </el-dialog>
  342. <!-- 添加或修改参数配置对话框 -->
  343. <el-dialog :title="title" :visible.sync="open" width="700px" append-to-body>
  344. <el-form ref="form" :model="form" :rules="rules" label-width="80px">
  345. <el-row>
  346. <el-col :span="12">
  347. <!-- <el-form-item label="员工账号" prop="userName">-->
  348. <!-- <el-input v-model="form.userName" placeholder="请输入员工后台账号" />-->
  349. <!-- </el-form-item>-->
  350. <el-form-item label="员工姓名" prop="nickName">
  351. <el-input v-model="form.nickName" placeholder="请输入员工后台昵称" />
  352. </el-form-item>
  353. </el-col>
  354. <el-col :span="12">
  355. <el-form-item label="归属部门" prop="deptId">
  356. <treeselect v-model="form.deptId" :options="deptOptions" :show-count="true" placeholder="请选择归属部门" />
  357. </el-form-item>
  358. </el-col>
  359. </el-row>
  360. <el-row>
  361. <el-col :span="12">
  362. <el-form-item label="手机号码" prop="phonenumber">
  363. <el-input v-model="form.phonenumber" placeholder="请输入手机号码" maxlength="11" />
  364. </el-form-item>
  365. </el-col>
  366. <el-col :span="12">
  367. <el-form-item label="邮箱" prop="email">
  368. <el-input v-model="form.email" placeholder="请输入邮箱" maxlength="50" />
  369. </el-form-item>
  370. </el-col>
  371. </el-row>
  372. <el-row>
  373. <el-col :span="12">
  374. <el-form-item label="员工账号" prop="userName">
  375. <el-input v-model="form.userName" placeholder="请输入员工工号" />
  376. </el-form-item>
  377. </el-col>
  378. <el-col :span="12">
  379. <el-form-item v-if="form.userId == undefined" label="用户密码" prop="password">
  380. <el-input v-model="form.password" placeholder="请输入用户密码" type="password" show-password />
  381. </el-form-item>
  382. </el-col>
  383. </el-row>
  384. <el-row>
  385. <el-col :span="12">
  386. <el-form-item label="员工性别">
  387. <el-select v-model="form.sex" placeholder="请选择">
  388. <el-option v-for="dict in sexOptions" :key="dict.dictValue" :label="dict.dictLabel" :value="dict.dictValue"></el-option>
  389. </el-select>
  390. </el-form-item>
  391. </el-col>
  392. <el-col :span="12">
  393. <el-form-item label="状态">
  394. <el-radio-group v-model="form.status">
  395. <el-radio v-for="dict in statusOptions" :key="dict.dictValue" :label="dict.dictValue">{{dict.dictLabel}}</el-radio>
  396. </el-radio-group>
  397. </el-form-item>
  398. </el-col>
  399. </el-row>
  400. <el-row>
  401. <el-col :span="12">
  402. <el-form-item label="岗位">
  403. <el-select v-model="form.postIds" multiple placeholder="请选择">
  404. <el-option v-for="item in postOptions" :key="item.postId" :label="item.postName" :value="item.postId" :disabled="item.status == 1"></el-option>
  405. </el-select>
  406. </el-form-item>
  407. </el-col>
  408. <el-col :span="12">
  409. <el-form-item label="角色">
  410. <el-select v-model="form.roleIds" multiple placeholder="请选择">
  411. <el-option v-for="item in roleOptions" :key="item.roleId" :label="item.roleName" :value="item.roleId" :disabled="item.status == 1"></el-option>
  412. </el-select>
  413. </el-form-item>
  414. </el-col>
  415. </el-row>
  416. <el-row>
  417. <el-col :span="12">
  418. <el-form-item label="身份证号">
  419. <el-input v-model="form.idCard" placeholder="请输入身份证号" maxlength="18" />
  420. </el-form-item>
  421. </el-col>
  422. <el-col :span="12">
  423. <el-form-item label="销售区域" prop="addressId">
  424. <el-select v-model="form.addressId" filterable placeholder="请选择所属销售的区域" style="width: 200px;">
  425. <el-option
  426. v-for="item in citysAreaList"
  427. :key="item.cityId"
  428. :label="item.cityName"
  429. :value="item.cityId"
  430. ></el-option>
  431. </el-select>
  432. </el-form-item>
  433. </el-col>
  434. </el-row>
  435. <!-- <el-row>-->
  436. <!-- <el-col :span="24">-->
  437. <!-- <el-form-item label="数据权限">-->
  438. <!-- <el-radio-group v-model="form.userType">-->
  439. <!-- <el-radio v-for="dict in userTypeOptions" :key="dict.dictValue" :label="dict.dictValue">{{dict.dictLabel}}</el-radio>-->
  440. <!-- </el-radio-group>-->
  441. <!-- </el-form-item>-->
  442. <!-- </el-col>-->
  443. <!-- </el-row>-->
  444. <!-- <el-row>
  445. <el-col :span="24">
  446. <el-form-item label="看课域名">
  447. <el-input
  448. v-model="form.domain"
  449. style="width: 250px"
  450. placeholder="请生成域名"
  451. @change="onDomainBlur"
  452. disabled
  453. ></el-input>
  454. <el-button type="primary" style="margin-left: 20px" @click="generateDomain">生成域名</el-button>
  455. </el-form-item>
  456. </el-col>
  457. </el-row>-->
  458. <el-row>
  459. <el-col :span="24">
  460. <el-form-item label="备注">
  461. <el-input v-model="form.remark" type="textarea" placeholder="请输入内容"></el-input>
  462. </el-form-item>
  463. </el-col>
  464. </el-row>
  465. </el-form>
  466. <div slot="footer" class="dialog-footer">
  467. <el-button type="primary" @click="submitForm">确 定</el-button>
  468. <el-button @click="cancel">取 消</el-button>
  469. </div>
  470. </el-dialog>
  471. <el-dialog :title="title" :visible.sync="bindCompanyOpen" width="700px" append-to-body>
  472. <el-form ref="formBindCompany" :model="formBindCompany" :rules="bindCompanyRules" label-width="80px">
  473. <el-row>
  474. <el-col :span="12">
  475. <el-form-item label="企微主体" prop="corpId">
  476. <el-select v-model="formBindCompany.corpId" placeholder="企微主体" size="small">
  477. <el-option
  478. v-for="dict in myQwCompanyList"
  479. :key="dict.dictValue"
  480. :label="dict.dictLabel"
  481. :value="dict.dictValue"
  482. />
  483. </el-select>
  484. </el-form-item>
  485. </el-col>
  486. </el-row>
  487. <el-row>
  488. <el-col :span="12">
  489. <el-form-item label="归属部门" prop="deptId">
  490. <treeselect v-model="formBindCompany.deptId" :options="deptOptions" :show-count="true" placeholder="请选择归属部门" />
  491. </el-form-item>
  492. </el-col>
  493. </el-row>
  494. <el-row>
  495. <el-col :span="12">
  496. <el-form-item label="角色" prop="roleIds">
  497. <el-select v-model="formBindCompany.roleIds" multiple placeholder="请选择">
  498. <el-option v-for="item in roleOptions" :key="item.roleId" :label="item.roleName" :value="item.roleId "></el-option>
  499. </el-select>
  500. </el-form-item>
  501. </el-col>
  502. </el-row>
  503. <el-row>
  504. <el-col :span="12">
  505. <el-form-item label="销售区域" prop="addressId">
  506. <el-select v-model="formBindCompany.addressId" filterable placeholder="请选择所属销售的区域" style="width: 200px;">
  507. <el-option
  508. v-for="item in citysAreaList"
  509. :key="item.cityId"
  510. :label="item.cityName"
  511. :value="item.cityId"
  512. ></el-option>
  513. </el-select>
  514. </el-form-item>
  515. </el-col>
  516. </el-row>
  517. </el-form>
  518. <div slot="footer" class="dialog-footer">
  519. <el-button type="primary" @click="submitBingCompanyForm">确 定</el-button>
  520. <el-button @click="cancelBind">取 消</el-button>
  521. </div>
  522. </el-dialog>
  523. <!-- 修改 selectUser 组件的引用 -->
  524. <el-dialog :title="user.title" :visible.sync="user.open" width="1000px" append-to-body>
  525. <selectUser ref="selectUser" @bindQwUser="bindQwUser" @close="handleSelectUserClose"/>
  526. </el-dialog>
  527. <el-dialog :title="companyUserArea.title" :visible.sync="companyUserArea.open" width="300px" append-to-body>
  528. <el-select v-model="addressId" filterable placeholder="请选择所属销售的区域" style="width: 200px;">
  529. <el-option
  530. v-for="item in citysAreaList"
  531. :key="item.cityId"
  532. :label="item.cityName"
  533. :value="item.cityId"
  534. ></el-option>
  535. </el-select>
  536. <div slot="footer" style="text-align: center;">
  537. <el-button type="primary" @click="submitFormArea(addressId)">确 定</el-button>
  538. <el-button @click="cancelArea">取 消</el-button>
  539. </div>
  540. </el-dialog>
  541. <!-- 设置单独注册会员弹窗 -->
  542. <!-- 设置单独注册会员 -->
  543. <el-dialog title="设置单独注册会员" :visible.sync="registerOpen" width="400px" append-to-body>
  544. <el-form ref="registerForm" :model="registerForm" label-width="160px">
  545. <el-form-item label="是否开启单独注册">
  546. <el-switch v-model="registerForm.status" :active-value="true" :inactive-value="false"></el-switch>
  547. </el-form-item>
  548. </el-form>
  549. <template #footer>
  550. <div class="dialog-footer">
  551. <el-button type="primary" @click="submitRegisterForm">确 定</el-button>
  552. <el-button @click="registerOpen = false">取 消</el-button>
  553. </div>
  554. </template>
  555. </el-dialog>
  556. <!-- 允许注册会员 -->
  557. <el-dialog title="允许注册会员" :visible.sync="allowedAllRegisterOpen" width="400px" append-to-body>
  558. <el-form ref="allowedAllRegisterForm" :model="allowedAllRegisterForm" label-width="160px">
  559. <el-form-item label="是否允许注册会员">
  560. <el-switch v-model="allowedAllRegisterForm.status" :active-value="true" :inactive-value="false"></el-switch>
  561. </el-form-item>
  562. </el-form>
  563. <template #footer>
  564. <div class="dialog-footer">
  565. <el-button type="primary" @click="submitAllowedAllRegisterForm">确 定</el-button>
  566. <el-button @click="allowedAllRegisterOpen = false">取 消</el-button>
  567. </div>
  568. </template>
  569. </el-dialog>
  570. <el-dialog :title="bindCompanyUrl.title" v-if="bindCompanyUrl.open" :visible.sync="bindCompanyUrl.open" width="450px" append-to-body>
  571. <div style="padding-bottom:15px;" >
  572. <img :src="bindCompanyUrl.url" width="400px">
  573. </div>
  574. <div slot="footer" class="dialog-footer">
  575. <el-button @click="downloadImage(bindCompanyUrl.url, bindCompanyUrl.name+'.png')">下载二维码</el-button>
  576. </div>
  577. </el-dialog>
  578. <el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
  579. <el-upload
  580. ref="upload"
  581. :limit="1"
  582. accept=".xlsx, .xls"
  583. :headers="upload.headers"
  584. :action="upload.url + '?updateSupport=' + upload.updateSupport"
  585. :disabled="upload.isUploading"
  586. :on-progress="handleFileUploadProgress"
  587. :on-success="handleFileSuccess"
  588. :auto-upload="false"
  589. drag
  590. >
  591. <i class="el-icon-upload"></i>
  592. <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
  593. <div class="el-upload__tip text-center" slot="tip">
  594. <div class="el-upload__tip" slot="tip">
  595. </div>
  596. <span>仅允许导入xls、xlsx格式文件。</span>
  597. <el-link type="primary" :underline="false" style="font-size:12px;vertical-align: baseline;" @click="importTemplate">下载模板</el-link>
  598. </div>
  599. </el-upload>
  600. <div slot="footer" class="dialog-footer">
  601. <el-button type="primary" @click="submitFileForm">确 定</el-button>
  602. <el-button @click="upload.open = false">取 消</el-button>
  603. </div>
  604. </el-dialog>
  605. <el-dialog :title="doctor.title" :visible.sync="doctor.open" width="800px" append-to-body>
  606. <selectDoctor ref="selectDoctor" @bindCompanyUserDoctorId="bindCompanyUserDoctorId"></selectDoctor>
  607. </el-dialog>
  608. <!-- 绑定用户对话框 -->
  609. <el-dialog title="绑定用户" :visible.sync="bindUserDialog.open" width="900px" append-to-body @close="resetBindUserForm">
  610. <el-form :model="bindUserForm" label-width="100px">
  611. <el-form-item label="手机号码">
  612. <el-input
  613. v-model="bindUserForm.phone"
  614. placeholder="请输入手机号码(完全匹配)"
  615. clearable
  616. style="width: 300px;"
  617. @keyup.enter.native="queryFsUserByPhone"
  618. >
  619. <el-button slot="append" icon="el-icon-search" @click="queryFsUserByPhone">查询</el-button>
  620. </el-input>
  621. </el-form-item>
  622. </el-form>
  623. <!-- 已绑定用户信息 -->
  624. <div v-if="boundUsersList.length > 0" style="margin-bottom: 20px;">
  625. <el-divider content-position="left">已绑定用户</el-divider>
  626. <el-table :data="boundUsersList" border style="width: 100%">
  627. <el-table-column prop="userId" label="用户ID" width="100" align="center"></el-table-column>
  628. <el-table-column prop="nickname" label="用户名称" align="center"></el-table-column>
  629. <el-table-column prop="phone" label="电话" align="center"></el-table-column>
  630. </el-table>
  631. </div>
  632. <!-- 查询结果 -->
  633. <div v-if="fsUserList.length > 0">
  634. <el-divider content-position="left">查询结果(可多选)</el-divider>
  635. <el-table
  636. :data="fsUserList"
  637. border
  638. v-loading="bindUserLoading"
  639. @selection-change="handleFsUserSelectionChange"
  640. style="width: 100%"
  641. >
  642. <el-table-column type="selection" width="55" align="center"></el-table-column>
  643. <el-table-column prop="userId" label="用户ID" width="100" align="center"></el-table-column>
  644. <el-table-column prop="nickname" label="用户名称" align="center"></el-table-column>
  645. <el-table-column prop="phone" label="电话" align="center"></el-table-column>
  646. </el-table>
  647. </div>
  648. <div v-else-if="bindUserForm.phone && !bindUserLoading" style="text-align: center; padding: 20px; color: #909399;">
  649. 暂无查询结果
  650. </div>
  651. <div v-if="bindUserLoading" style="text-align: center; padding: 20px;">
  652. <i class="el-icon-loading"></i> 查询中...
  653. </div>
  654. <div slot="footer" class="dialog-footer">
  655. <el-button @click="bindUserDialog.open = false">取 消</el-button>
  656. <el-button type="primary" @click="submitBindUser" :disabled="selectedFsUserIds.length === 0">确 定</el-button>
  657. </div>
  658. </el-dialog>
  659. </div>
  660. </template>
  661. <script>
  662. import {
  663. qwList,
  664. delUser,
  665. addUser,
  666. getUser,
  667. updateUser,
  668. exportUser,
  669. resetUserPwd,
  670. importTemplate,
  671. getCitysAreaList,
  672. changeUserStatus,
  673. generateSubDomain,
  674. setIsRegisterMember,
  675. updateCompanyUserAreaList,
  676. isAllowedAllRegister, unBindDoctorId, bindDoctorId,updateBatchUserRoles,
  677. queryFsUserByPhone,
  678. batchBindCompanyUserId,
  679. getBoundUsers
  680. } from "@/api/company/companyUser";
  681. import { getToken } from "@/utils/auth";
  682. import { treeselect } from "@/api/company/companyDept";
  683. import Treeselect from "@riophae/vue-treeselect";
  684. import "@riophae/vue-treeselect/dist/vue-treeselect.css";
  685. import {bindQwUser, getQwUserList, addQwUser, getQwUser, getQwUserByIds,addQwUserName} from '@/api/qw/user';
  686. import { syncDept } from '@/api/qw/qwDept';
  687. import { getMyQwUserList,getMyQwCompanyList } from "@/api/qw/user";
  688. import selectUser from "@/views/company/components/selectQwUser.vue";
  689. import { getConfigByKey } from "@/api/company/companyConfig";
  690. import axios from "axios";
  691. import {addCodeUrl} from "../../../api/company/companyUser";
  692. import selectDoctor from "@/views/qw/user/selectDoctor.vue";
  693. import { mapGetters } from 'vuex';
  694. export default {
  695. name: "User",
  696. components: {selectDoctor, Treeselect ,selectUser},
  697. computed: {
  698. ...mapGetters({ currentUser: 'user' }),
  699. // 过滤后的用户列表
  700. filteredUserList() {
  701. if (!this.userList) return [];
  702. // 如果当前用户是管理员(userType='00'),显示所有数据
  703. if (this.currentUser && this.currentUser.userType === '00') {
  704. return this.userList;
  705. }
  706. // 如果不是管理员,过滤掉 userType='00' 的数据
  707. return this.userList.filter(item => item.userType !== '00');
  708. }
  709. },
  710. data() {
  711. return {
  712. doctor: {
  713. open: false,
  714. title: '绑定医生'
  715. },
  716. doctorForm: {
  717. userId: null,
  718. doctorId: null
  719. },
  720. uploadUrl: process.env.VUE_APP_BASE_API+"/company/user/common/uploadOSS",
  721. // 遮罩层
  722. loading: false,
  723. qwUserList:[],
  724. qwUserId:[],
  725. myQwCompanyList:[],
  726. qwUser:[],
  727. user:{
  728. open:false,
  729. title:"搜索企业"
  730. },
  731. // 选中数组
  732. ids: [],
  733. //允许注册会员
  734. isAllowedAllRegister: [],
  735. //是否单独注册
  736. isNeedRegisterMember: [],
  737. synform:{corpId:null},
  738. synOpen:false,
  739. synNameform:{corpId:null},
  740. synNameOpen:false,
  741. // 非单个禁用
  742. single: true,
  743. // 非多个禁用
  744. multiple: true,
  745. // 显示搜索条件
  746. showSearch: true,
  747. // 总条数
  748. total: 0,
  749. // 用户表格数据
  750. userList: null,
  751. // 弹出层标题
  752. title: "",
  753. // 部门树选项
  754. deptOptions: undefined,
  755. // 是否显示弹出层
  756. open: false,
  757. bindCompanyOpen: false,
  758. qwOpen:false,
  759. // 部门名称
  760. deptName: undefined,
  761. // 日期范围
  762. dateRange: [],
  763. // 状态数据字典
  764. statusOptions: [],
  765. // 性别状态字典
  766. sexOptions: [],
  767. // 岗位选项
  768. postOptions: [],
  769. // 角色选项
  770. roleOptions: [],
  771. userTypeOptions:[
  772. { "dictLabel": "临时管理员","dictValue": "02"},
  773. { "dictLabel": "普通用户","dictValue": "01"}
  774. ],
  775. qwForm:{
  776. id:null,
  777. companyUserId:null,
  778. },
  779. companyUserArea:{
  780. open:false,
  781. title:"分配区域",
  782. },
  783. //选择的区域
  784. addressId:null,
  785. citysAreaList:[],
  786. // 表单参数
  787. form: {},
  788. formBindCompany: {},
  789. bindCompanyUrl:{
  790. open:false,
  791. title:"绑定/注册销售二维码",
  792. name:null,
  793. url:null,
  794. },
  795. form1: {},
  796. defaultProps: {
  797. children: "children",
  798. label: "label",
  799. },
  800. // 用户导入参数
  801. upload: {
  802. // 是否显示弹出层(用户导入)
  803. open: false,
  804. // 弹出层标题(用户导入)
  805. title: "",
  806. // 是否禁用上传
  807. isUploading: false,
  808. // 是否更新已经存在的用户数据
  809. updateSupport: 0,
  810. // 设置上传的请求头部
  811. headers: { Authorization: "Bearer " + getToken() },
  812. // 上传的地址
  813. url: process.env.VUE_APP_BASE_API + "/company/user/importCompanyUser",
  814. },
  815. // 查询参数
  816. queryParams: {
  817. pageNum: 1,
  818. pageSize: 10,
  819. userId: null,
  820. userName: null,
  821. phonenumber: null,
  822. status: null,
  823. deptId: null,
  824. qwStatus:null,
  825. },
  826. qwStatusOptions:[],
  827. registerOpen: false,
  828. registerForm: {
  829. status: false,
  830. },
  831. // 表单校验
  832. rules: {
  833. userName: [
  834. { required: true, message: "员工工号不能为空", trigger: "blur" },
  835. ],
  836. nickName: [
  837. { required: true, message: "员工姓名不能为空", trigger: "blur" },
  838. ],
  839. deptId: [
  840. { required: true, message: "归属部门不能为空", trigger: "blur" },
  841. ],
  842. addressId: [
  843. { required: true, message: "销售所属区域不能为空", trigger: "blur" },
  844. ],
  845. password: [
  846. { required: true, message: "员工密码不能为空", trigger: "blur" },
  847. {
  848. pattern: /^(?=.*[A-Za-z])(?=.*\d)(?=.*[^A-Za-z0-9]).{8,20}$/,
  849. message: "密码长度为 8-20 位,必须包含字母、数字和特殊字符",
  850. trigger: ["blur", "change"],
  851. }
  852. ],
  853. idCard: [
  854. { required: true, message: "身份证号不能为空", trigger: "blur" },
  855. ],
  856. // email: [
  857. // { required: true, message: "邮箱地址不能为空", trigger: "blur" },
  858. // {
  859. // type: "email",
  860. // message: "'请输入正确的邮箱地址",
  861. // trigger: ["blur", "change"],
  862. // },
  863. // ],
  864. phonenumber: [
  865. { required: true, message: "手机号码不能为空", trigger: "blur" },
  866. {
  867. pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
  868. message: "请输入正确的手机号码",
  869. trigger: "blur",
  870. },
  871. ],
  872. },
  873. // 表单校验
  874. bindCompanyRules: {
  875. deptId: [
  876. { required: true, message: "归属部门不能为空", trigger: "blur" },
  877. ],
  878. addressId: [
  879. { required: true, message: "销售所属区域不能为空", trigger: "blur" },
  880. ],
  881. roleIds: [
  882. { required: true, message: "角色不能为空", trigger: "blur" },
  883. ],
  884. corpId: [
  885. { required: true, message: "角色不能为空", trigger: "blur" },
  886. ],
  887. },
  888. // 是否允许注册会员开关
  889. allowedAllRegisterOpen: false,
  890. allowedAllRegisterForm: {
  891. status: true
  892. },
  893. // 在 data() 中添加
  894. batchRoleDialogVisible: false,
  895. selectedRoleIds: [],
  896. batchRoleForm: {
  897. userIds: [],
  898. roleIds: []
  899. },
  900. // 绑定用户相关
  901. bindUserDialog: {
  902. open: false,
  903. title: '绑定用户'
  904. },
  905. bindUserForm: {
  906. phone: '',
  907. companyUserId: null
  908. },
  909. fsUserList: [],
  910. selectedFsUserIds: [],
  911. boundUsersList: [],
  912. bindUserLoading: false,
  913. };
  914. },
  915. watch: {
  916. // 根据名称筛选部门树
  917. deptName(val) {
  918. this.$refs.tree.filter(val);
  919. },
  920. },
  921. created() {
  922. this.getList();
  923. this.getTreeselect();
  924. this.getDicts("sys_normal_disable").then((response) => {
  925. this.statusOptions = response.data;
  926. });
  927. this.getDicts("company_user_sex").then((response) => {
  928. this.sexOptions = response.data;
  929. });
  930. this.getDicts("sys_qw_user_status").then(response => {
  931. this.qwStatusOptions = response.data;
  932. });
  933. getConfigByKey("his.login").then(response => {
  934. this.form1 =JSON.parse(response.data.configValue);
  935. });
  936. getCitysAreaList().then(res=>{
  937. this.citysAreaList=res.data;
  938. })
  939. getMyQwCompanyList().then(response => {
  940. this.myQwCompanyList = response.data;
  941. });
  942. },
  943. methods: {
  944. onDomainBlur() {
  945. if (this.form.domain != null) {
  946. let value = this.form.domain.trim();
  947. // 强制只保留第一个 http://
  948. const httpCount = (value.match(/http:\/\//g) || []).length;
  949. if (httpCount > 1) {
  950. value = value.replace(/(http:\/\/)+/, 'http://'); // 只留第一个
  951. }
  952. // 如果不是 http:// 开头,自动补充
  953. if (!value.startsWith('http://')) {
  954. value = 'http://' + value.replace(/^https?:\/\//, ''); // 去掉其他 http(s):// 再补
  955. }
  956. this.form.domain = value; // 重新赋值,保证输入正确
  957. // 正则校验最终格式,提醒用户
  958. const domainPattern = /^http:\/\/([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}$/;
  959. if (!domainPattern.test(this.form.domain)) {
  960. return this.$message.error('请输入正确格式的域名,如:http://xxx.xxx.com');
  961. }
  962. }
  963. },
  964. // 添加处理 selectUser 关闭的方法
  965. handleSelectUserClose() {
  966. this.user.open = false
  967. // 如果 selectUser 组件有 clearSelection 方法,也可以调用
  968. if (this.$refs.selectUser && typeof this.$refs.selectUser.clearSelection === 'function') {
  969. this.$refs.selectUser.clearSelection()
  970. }
  971. },
  972. // edit G start
  973. // 修改 selectQwUser 方法
  974. selectQwUser() {
  975. this.user.open = true;
  976. // 在下次DOM更新后设置已选中的项
  977. this.$nextTick(() => {
  978. if (this.$refs.selectUser && this.qwUserList.length > 0) {
  979. // 将已选中的用户传递给子组件
  980. this.$refs.selectUser.setSelectedUsers(this.qwUserList);
  981. }
  982. });
  983. },
  984. // 修改 bindQwUser 方法
  985. bindQwUser(row) {
  986. // this.user.open = false; // 暂时注释掉这行,改为在 handleBatchBind 中处理
  987. if (!this.qwUserList.some(item => item.id == row.id)) {
  988. this.qwUserList.push(row)
  989. }
  990. if (!this.qwUser.some(item => item == row.id)) {
  991. this.qwUser.push(row.id)
  992. }
  993. },
  994. // 修改 qwBind 方法
  995. qwBind(row) {
  996. this.qwUser = [];
  997. this.qwUserList = [];
  998. this.qwForm.companyUserId = row.userId;
  999. getUser(row.userId).then((response) => {
  1000. if (response.data.qwUserId != null) {
  1001. // 保存已绑定的企微用户ID列表
  1002. this.qwUser = ((response.data.qwUserId).split(",").map(Number));
  1003. getQwUserByIds(this.qwUser).then(res => {
  1004. this.qwUserList = res.data;
  1005. });
  1006. }
  1007. // 先打开"绑定企微账号"对话框
  1008. this.qwOpen = true;
  1009. });
  1010. },
  1011. // 在 methods 中添加批量修改角色的方法
  1012. batchEditRole() {
  1013. if (this.ids.length === 0) {
  1014. this.$message.warning("请至少选择一个用户");
  1015. return;
  1016. }
  1017. // 获取角色列表数据
  1018. getUser().then((response) => {
  1019. this.roleOptions = response.roles;
  1020. this.batchRoleDialogVisible = true;
  1021. this.selectedRoleIds = []; // 清空之前的选择
  1022. });
  1023. },
  1024. // 添加批量角色更新提交方法
  1025. submitBatchRoles() {
  1026. // 验证选择的角色
  1027. if (!this.selectedRoleIds || this.selectedRoleIds.length === 0) {
  1028. this.$message.warning("请至少选择一个角色");
  1029. return;
  1030. }
  1031. console.log(this.ids)
  1032. console.log(this.selectedRoleIds)
  1033. // 调用API批量更新用户角色
  1034. updateBatchUserRoles({ userIds: this.ids, roleIds: this.selectedRoleIds })
  1035. .then(response => {
  1036. if (response.code === 200) {
  1037. this.$message.success("批量修改角色成功");
  1038. this.batchRoleDialogVisible = false;
  1039. this.getList(); // 刷新列表
  1040. }
  1041. });
  1042. },
  1043. // edit G end
  1044. /** 查询用户列表 */
  1045. getList() {
  1046. this.loading = true;
  1047. qwList(this.addDateRange(this.queryParams, this.dateRange)).then(
  1048. (response) => {
  1049. this.userList = response.rows;
  1050. this.total = response.total;
  1051. this.loading = false;
  1052. console.log(" this.userList ", this.userList)
  1053. }
  1054. );
  1055. },
  1056. handleClosegroupUser(list) {
  1057. const index = this.qwUser.findIndex(t => t === list);
  1058. if (index !== -1) {
  1059. this.qwUser.splice(index, 1);
  1060. }
  1061. },
  1062. /** 查询部门下拉树结构 */
  1063. getTreeselect() {
  1064. treeselect().then((response) => {
  1065. this.deptOptions = response.data;
  1066. });
  1067. },
  1068. // 筛选节点
  1069. filterNode(value, data) {
  1070. if (!value) return true;
  1071. return data.label.indexOf(value) !== -1;
  1072. },
  1073. // 节点单击事件
  1074. handleNodeClick(data) {
  1075. this.queryParams.deptId = data.id;
  1076. this.getList();
  1077. },
  1078. // 用户状态修改
  1079. handleStatusChange(row) {
  1080. let text = row.status === "0" ? "启用" : "停用";
  1081. this.$confirm(
  1082. '确认要"' + text + '""' + row.userName + '"用户吗?',
  1083. "警告",
  1084. {
  1085. confirmButtonText: "确定",
  1086. cancelButtonText: "取消",
  1087. type: "warning",
  1088. }
  1089. )
  1090. .then(function() {
  1091. return changeUserStatus(row.userId, row.status);
  1092. })
  1093. .then(() => {
  1094. this.msgSuccess(text + "成功");
  1095. })
  1096. .catch(function() {
  1097. row.status = row.status === "0" ? "1" : "0";
  1098. });
  1099. },
  1100. // 取消按钮
  1101. cancel() {
  1102. this.open = false;
  1103. this.reset();
  1104. },
  1105. cancelBind() {
  1106. this.bindCompanyOpen = false;
  1107. this.resetBindCompany();
  1108. },
  1109. submitFormArea(address) {
  1110. const uIds = this.ids;
  1111. if (address == null) {
  1112. this.$message.error("请选择地区");
  1113. return;
  1114. }
  1115. updateCompanyUserAreaList({ userIds: uIds, addressId: address }).then(res => {
  1116. this.companyUserArea.open = false;
  1117. this.getList();
  1118. this.msgSuccess("操作成功");
  1119. })
  1120. },
  1121. cancelArea() {
  1122. this.companyUserArea.open = false;
  1123. this.addressId = null;
  1124. },
  1125. qwCancel() {
  1126. this.qwOpen = false;
  1127. this.qwUserId = null;
  1128. },
  1129. handerCompanyUserAreaList() {
  1130. this.companyUserArea.open = true;
  1131. },
  1132. // 表单重置
  1133. reset() {
  1134. this.form = {
  1135. userId: undefined,
  1136. deptId: undefined,
  1137. userName: undefined,
  1138. nickName: undefined,
  1139. password: undefined,
  1140. idCard: undefined,
  1141. phonenumber: undefined,
  1142. userType: "01",
  1143. email: undefined,
  1144. sex: undefined,
  1145. status: "0",
  1146. remark: undefined,
  1147. domain: null,
  1148. postIds: [],
  1149. roleIds: [],
  1150. };
  1151. this.resetForm("form");
  1152. },
  1153. resetBindCompany() {
  1154. this.formBindCompany = {
  1155. deptId: null,
  1156. addressId: null,
  1157. roleIds: [],
  1158. };
  1159. this.resetForm("formBindCompany");
  1160. },
  1161. /** 搜索按钮操作 */
  1162. handleQuery() {
  1163. this.queryParams.page = 1;
  1164. this.getList();
  1165. },
  1166. /** 重置按钮操作 */
  1167. resetQuery() {
  1168. this.dateRange = [];
  1169. this.resetForm("queryForm");
  1170. this.handleQuery();
  1171. },
  1172. // 多选框选中数据
  1173. handleSelectionChange(selection) {
  1174. this.ids = selection.map((item) => item.userId);
  1175. this.isNeedRegisterMember = selection.map((item) => item.isNeedRegisterMember);
  1176. this.isAllowedAllRegister = selection.map((item) => item.isAllowedAllRegister);
  1177. this.single = selection.length != 1;
  1178. this.multiple = !selection.length;
  1179. },
  1180. /** 新增按钮操作 */
  1181. handleAdd() {
  1182. this.reset();
  1183. this.getTreeselect();
  1184. getUser().then((response) => {
  1185. this.postOptions = response.posts;
  1186. this.roleOptions = response.roles;
  1187. this.open = true;
  1188. this.title = "添加员工";
  1189. this.form.password = this.form1.loginPassword;
  1190. console.log(" this.form1 ", this.form1)
  1191. });
  1192. },
  1193. handleBindCompanyUserCode() {
  1194. this.reset();
  1195. this.getTreeselect();
  1196. getUser().then((response) => {
  1197. this.postOptions = response.posts;
  1198. this.roleOptions = response.roles;
  1199. this.bindCompanyOpen = true;
  1200. this.title = "创建 新增/绑定销售 的二维码";
  1201. });
  1202. },
  1203. /** 修改按钮操作 */
  1204. handleUpdate(row) {
  1205. this.reset();
  1206. this.getTreeselect();
  1207. const userId = row.userId || this.ids;
  1208. getUser(userId).then((response) => {
  1209. this.form = response.data;
  1210. this.postOptions = response.posts;
  1211. this.roleOptions = response.roles;
  1212. this.form.postIds = response.postIds;
  1213. this.form.roleIds = response.roleIds;
  1214. this.open = true;
  1215. this.title = "修改员工";
  1216. this.form.password = "";
  1217. });
  1218. },
  1219. /** 重置密码按钮操作 */
  1220. handleResetPwd(row) {
  1221. this.$prompt('请输入"' + row.userName + '"的新密码', "提示", {
  1222. confirmButtonText: "确定",
  1223. cancelButtonText: "取消",
  1224. inputPlaceholder: "8-20 位,包含字母、数字和特殊字符",
  1225. inputValidator: (value) => {
  1226. const pattern = /^(?=.*[A-Za-z])(?=.*\d)(?=.*[^A-Za-z0-9]).{8,20}/;
  1227. const hasChinese = /[\u4e00-\u9fa5]/.test(value);
  1228. const hasFullWidth = /[!-~]/.test(value);
  1229. if (hasChinese) return '不能包含中文字符';
  1230. if (hasFullWidth) return '不能包含全角符号,请使用英文输入法';
  1231. if (!pattern.test(value)) return '密码格式错误:需包含字母、数字和英文特殊字符,长度为 8-20 位';
  1232. return true;
  1233. }
  1234. })
  1235. .then(({ value }) => {
  1236. resetUserPwd(row.userId, value).then((response) => {
  1237. if (response.code === 200) {
  1238. this.msgSuccess("修改成功,新密码是:" + value);
  1239. }
  1240. });
  1241. })
  1242. .catch(() => {
  1243. });
  1244. },
  1245. /** 提交按钮 */
  1246. submitForm: function() {
  1247. // this.onDomainBlur();
  1248. // const domainPattern = /^http:\/\/([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}$/;
  1249. // if (this.form.domain!=null && !domainPattern.test(this.form.domain)) {
  1250. // this.$message.error('请输入正确格式的域名,如:http://xxx.xxx.com');
  1251. // return;
  1252. // }
  1253. this.$refs["form"].validate((valid) => {
  1254. if (valid) {
  1255. if (this.form.userId != undefined) {
  1256. updateUser(this.form).then((response) => {
  1257. if (response.code === 200) {
  1258. this.msgSuccess("修改成功");
  1259. this.open = false;
  1260. this.getList();
  1261. }
  1262. });
  1263. } else {
  1264. addUser(this.form).then((response) => {
  1265. if (response.code === 200) {
  1266. this.msgSuccess("新增成功");
  1267. this.open = false;
  1268. this.getList();
  1269. }
  1270. });
  1271. }
  1272. }
  1273. });
  1274. },
  1275. downloadImage(imageSrc, fileName) {
  1276. const link = document.createElement('a');
  1277. link.href = imageSrc;
  1278. link.download = fileName || '绑定或新增销售.png';
  1279. document.body.appendChild(link);
  1280. link.click();
  1281. document.body.removeChild(link);
  1282. },
  1283. submitBingCompanyForm: function() {
  1284. this.$refs["formBindCompany"].validate((valid) => {
  1285. if (valid) {
  1286. let loadingRock = this.$loading({
  1287. lock: true,
  1288. text: '生成二维码中~~请不要刷新页面!!',
  1289. spinner: 'el-icon-loading',
  1290. background: 'rgba(0, 0, 0, 0.7)'
  1291. });
  1292. addCodeUrl(this.formBindCompany).then((response) => {
  1293. this.bindCompanyOpen = false;
  1294. this.bindCompanyUrl.url = response.data.url
  1295. this.bindCompanyUrl.open = true;
  1296. this.bindCompanyUrl.name = "绑定或新增 销售二维码";
  1297. }).finally(res => {
  1298. loadingRock.close();
  1299. })
  1300. }
  1301. });
  1302. },
  1303. /**
  1304. * 同步企业微信员工
  1305. */
  1306. synSubmitForm() {
  1307. this.synOpen = false;
  1308. this.loading = true;
  1309. /*this.msgSuccess("");
  1310. let loadingRock = this.$loading({
  1311. lock: true,
  1312. text: '同步中.....请等待.....请不要重复点击!!',
  1313. spinner: 'el-icon-loading',
  1314. background: 'rgba(0, 0, 0, 0.7)'
  1315. });*/
  1316. addQwUser(this.synform.corpId).then(response => {
  1317. //this.msgSuccess("同步成功");
  1318. this.msgSuccess("正在同步中...");
  1319. this.getList();
  1320. this.synOpen = false;
  1321. }).finally(() => {
  1322. this.loading = false;
  1323. this.synOpen = false;
  1324. //loadingRock.close();
  1325. });
  1326. },
  1327. synNameSubmitForm() {
  1328. this.synNameOpen = false;
  1329. this.loading = true;
  1330. addQwUserName(this.synNameform.corpId).then(response => {
  1331. // this.msgSuccess("同步成功");
  1332. this.msgSuccess("正在同步中...");
  1333. this.getList();
  1334. this.synNameOpen = false;
  1335. }).finally(() => {
  1336. this.loading = false;
  1337. this.synNameOpen = false;
  1338. //loadingRock.close();
  1339. });
  1340. },
  1341. /**
  1342. * 同步企业微信部门
  1343. */
  1344. qwSyncDept() {
  1345. syncDept().then(response => {
  1346. this.msgSuccess("同步成功");
  1347. this.getList();
  1348. }).catch(() => {
  1349. this.msgError("同步失败:" + response.msg);
  1350. })
  1351. },
  1352. qwSubmitForm() {
  1353. let loadingRock = this.$loading({
  1354. lock: true,
  1355. text: '绑定中.....同步客户信息中.....',
  1356. spinner: 'el-icon-loading',
  1357. background: 'rgba(0, 0, 0, 0.7)'
  1358. });
  1359. this.qwForm.id = (this.qwUser).join(',');
  1360. bindQwUser(this.qwForm).then(response => {
  1361. this.msgSuccess("绑定成功");
  1362. this.qwOpen = false;
  1363. this.getList();
  1364. this.qwUserId = null;
  1365. this.qwUser = [];
  1366. }).finally(res => {
  1367. loadingRock.close()
  1368. });
  1369. },
  1370. /** 删除按钮操作 */
  1371. handleDelete(row) {
  1372. // 确保 userIds 始终是数组
  1373. let userIds = row.userId || this.ids;
  1374. if (!Array.isArray(userIds)) {
  1375. userIds = [userIds];
  1376. }
  1377. // 筛选出 userType 为 '00' 的 userId
  1378. const excludedUserIds = this.userList
  1379. .filter(user => user.userType == '00')
  1380. .map(user => user.userId);
  1381. // 从 userIds 中剔除这些 userId
  1382. const finalUserIds = userIds.filter(userId =>
  1383. !excludedUserIds.includes(userId)
  1384. );
  1385. if (finalUserIds.length === 0) {
  1386. return this.msgInfo("除管理员外无其他的账号,请重新选择");
  1387. }
  1388. this.$confirm(
  1389. '是否确认删除员工编号为"' + finalUserIds + '"的数据项?【注意:删除后绑定的企业微信相关信息可能会错乱!!】',
  1390. "警告",
  1391. {
  1392. confirmButtonText: "确定",
  1393. cancelButtonText: "取消",
  1394. type: "warning",
  1395. }
  1396. )
  1397. .then(function() {
  1398. return delUser(finalUserIds);
  1399. })
  1400. .then(() => {
  1401. this.getList();
  1402. this.msgSuccess("删除成功");
  1403. })
  1404. .catch(function() {
  1405. });
  1406. },
  1407. /** 导出按钮操作 */
  1408. handleExport() {
  1409. const queryParams = this.queryParams;
  1410. this.$confirm("是否确认导出所有用户数据项?", "警告", {
  1411. confirmButtonText: "确定",
  1412. cancelButtonText: "取消",
  1413. type: "warning",
  1414. })
  1415. .then(function() {
  1416. return exportUser(queryParams);
  1417. })
  1418. .then((response) => {
  1419. this.download(response.msg);
  1420. })
  1421. .catch(function() {
  1422. });
  1423. },
  1424. /** 导入按钮操作 */
  1425. handleImport() {
  1426. this.upload.title = "用户导入";
  1427. this.upload.open = true;
  1428. },
  1429. /** 下载模板操作 */
  1430. importTemplate() {
  1431. importTemplate().then((response) => {
  1432. this.download(response.msg);
  1433. });
  1434. },
  1435. // 文件上传中处理
  1436. handleFileUploadProgress(event, file, fileList) {
  1437. this.upload.isUploading = true;
  1438. },
  1439. // 文件上传成功处理
  1440. handleFileSuccess(response, file, fileList) {
  1441. this.upload.open = false;
  1442. this.upload.isUploading = false;
  1443. this.$refs.upload.clearFiles();
  1444. this.$alert(response.msg, "导入结果", { dangerouslyUseHTMLString: true });
  1445. this.getList();
  1446. },
  1447. // 提交上传文件
  1448. submitFileForm() {
  1449. this.$refs.upload.submit();
  1450. },
  1451. generateDomain() {
  1452. let queryParams;
  1453. if (this.form.userId) {
  1454. queryParams = {
  1455. 'userId': this.form.userId,
  1456. }
  1457. }
  1458. generateSubDomain(queryParams).then(response => {
  1459. this.form.domain = response.data
  1460. });
  1461. },
  1462. /** 设置单独注册会员按钮操作 */
  1463. handleSetRegister() {
  1464. this.registerOpen = true;
  1465. if (this.isNeedRegisterMember && this.isNeedRegisterMember.some(item => item === 0)) {
  1466. this.registerForm.status = false;
  1467. } else {
  1468. this.registerForm.status = true;
  1469. }
  1470. },
  1471. /** 提交设置单独注册会员 */
  1472. submitRegisterForm() {
  1473. setIsRegisterMember({ status: this.registerForm.status }, this.ids).then(response => {
  1474. if (response.code === 200) {
  1475. this.msgSuccess("设置成功");
  1476. this.registerOpen = false;
  1477. this.getList();
  1478. }
  1479. });
  1480. },
  1481. /** 开关是否允许所有方式注册会员 */
  1482. handleAllowedAllRegister() {
  1483. this.allowedAllRegisterOpen = true;
  1484. if (this.isAllowedAllRegister && this.isAllowedAllRegister.some(item => item === 0)) {
  1485. this.allowedAllRegisterForm.status = false;
  1486. } else {
  1487. this.allowedAllRegisterForm.status = true;
  1488. }
  1489. // this.allowedAllRegisterForm.status = true;
  1490. },
  1491. // 提交
  1492. submitAllowedAllRegisterForm() {
  1493. isAllowedAllRegister({ status: this.allowedAllRegisterForm.status }, this.ids).then(response => {
  1494. if (response.code === 200) {
  1495. this.msgSuccess("操作成功");
  1496. this.allowedAllRegisterOpen = false;
  1497. this.getList();
  1498. }
  1499. });
  1500. },
  1501. /**
  1502. * 上传文件之前的钩子,参数为上传的文件,若返回 false 或者返回 Promise且被 reject,则停止上传。
  1503. * @param {File} file - 用户选择的文件对象
  1504. * @param {Object} row - 当前行的数据对象
  1505. */
  1506. beforeImageUpload(file, row) {
  1507. // 清除之前的错误信息
  1508. this.$set(row, 'uploadError', '');
  1509. const isJPG = file.type === 'image/jpeg';
  1510. const isPNG = file.type === 'image/png';
  1511. const isGIF = file.type === 'image/gif'; // 根据需要添加更多格式
  1512. const isValidFormat = isJPG || isPNG || isGIF;
  1513. const isLt2M = file.size / 1024 / 1024 < 2; // 限制图片大小为 2MB
  1514. if (!isValidFormat) {
  1515. const errorMsg = '上传二维码图片只能是 JPG/PNG/GIF 格式!';
  1516. this.$message.error(errorMsg);
  1517. this.$set(row, 'uploadError', errorMsg); // 在行内显示错误
  1518. return false;
  1519. }
  1520. if (!isLt2M) {
  1521. const errorMsg = '上传二维码图片大小不能超过 2MB!';
  1522. this.$message.error(errorMsg);
  1523. this.$set(row, 'uploadError', errorMsg); // 在行内显示错误
  1524. return false;
  1525. }
  1526. return true; // 校验通过,允许上传
  1527. },
  1528. /**
  1529. * 自定义上传方法
  1530. * @param {Object} options - Element UI upload 组件传递的参数,包含 file, onSuccess, onError, onProgress 等
  1531. * @param {Object} row - 当前行的数据对象
  1532. */
  1533. async handleCustomUpload(options, row) {
  1534. const file = options.file;
  1535. const formData = new FormData();
  1536. formData.append('file', file);
  1537. formData.append('userId', row.userId)
  1538. this.$set(row, 'uploading', true);
  1539. this.$set(row, 'uploadError', '');
  1540. try {
  1541. const response = await axios.post(this.uploadUrl, formData, {
  1542. headers: {
  1543. 'Content-Type': 'multipart/form-data',
  1544. },
  1545. onUploadProgress: progressEvent => {
  1546. const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);
  1547. console.log(`上传进度: ${percentCompleted}%`);
  1548. }
  1549. });
  1550. if (response.data && (response.data.url || (response.data.data && response.data.data.url))) {
  1551. const imageUrl = response.data.url || response.data.data.url;
  1552. this.$set(row, 'qrCodeWeixin', imageUrl); // 更新行数据中的图片URL
  1553. this.$message.success('图片上传成功!');
  1554. options.onSuccess(response.data, file); // 通知el-upload上传成功 (虽然我们自定义了,但调用一下也无妨)
  1555. } else {
  1556. const errorMsg = response.data.message || '图片上传失败,服务器未返回有效URL';
  1557. this.$message.error(errorMsg);
  1558. this.$set(row, 'uploadError', errorMsg);
  1559. options.onError(new Error(errorMsg), file); // 通知el-upload上传失败
  1560. }
  1561. } catch (error) {
  1562. console.error('上传失败:', error);
  1563. let errorMsg = '图片上传失败';
  1564. if (error.response && error.response.data && error.response.data.message) {
  1565. errorMsg = error.response.data.message;
  1566. } else if (error.message) {
  1567. errorMsg = error.message;
  1568. }
  1569. this.$message.error(errorMsg);
  1570. this.$set(row, 'uploadError', errorMsg);
  1571. options.onError(error, file); // 通知el-upload上传失败
  1572. } finally {
  1573. this.$set(row, 'uploading', false); // 无论成功失败,结束上传状态
  1574. }
  1575. },
  1576. requestUpload() {
  1577. },
  1578. beforeUpload() {
  1579. console.log(file.type)
  1580. const isPic =
  1581. file.type === 'image/jpeg' ||
  1582. file.type === 'image/png' ||
  1583. file.type === 'image/gif' ||
  1584. file.type === 'image/jpg' ||
  1585. file.type === 'audio/mpeg'
  1586. const isLt2M = file.size / 1024 / 1024 < 2
  1587. if (!isPic) {
  1588. this.$message.error('上传图片只能是 JPG、JPEG、PNG、GIF 格式!')
  1589. return false
  1590. }
  1591. if (!isLt2M) {
  1592. this.$message.error('上传头像图片大小不能超过 2MB!')
  1593. }
  1594. return isPic && isLt2M
  1595. },
  1596. handleUpdateDoctor(row) {
  1597. this.doctor.title = "绑定医生"
  1598. this.doctor.open = true;
  1599. this.doctorForm.userId = row.userId;
  1600. },
  1601. bindCompanyUserDoctorId(row) {
  1602. console.log(row)
  1603. this.doctorForm.doctorId = row;
  1604. bindDoctorId(this.doctorForm).then(res => {
  1605. if (res.code == 200) {
  1606. this.$message.success('绑定成功')
  1607. } else {
  1608. this.$message.error('绑定失败:', res.msg)
  1609. }
  1610. this.getList()
  1611. this.doctor.open = false;
  1612. })
  1613. },
  1614. handleUnBindUserId(val) {
  1615. this.$confirm(
  1616. '确认解绑医生:<span style="color: green;">' + val.nickName + '' +
  1617. '</span> 的医生?',
  1618. {
  1619. confirmButtonText: "确定",
  1620. cancelButtonText: "取消",
  1621. type: "warning",
  1622. dangerouslyUseHTMLString: true // 允许使用 HTML 字符串
  1623. }
  1624. ).then(() => {
  1625. return unBindDoctorId(val.userId);
  1626. }).then(response => {
  1627. this.getList();
  1628. this.msgSuccess("解绑成功");
  1629. }).finally(res => {
  1630. this.getList();
  1631. })
  1632. },
  1633. /** 绑定用户按钮操作 */
  1634. handleBindUser(row) {
  1635. this.bindUserForm.companyUserId = row.userId;
  1636. this.bindUserForm.phone = '';
  1637. this.fsUserList = [];
  1638. this.selectedFsUserIds = [];
  1639. this.boundUsersList = [];
  1640. this.bindUserDialog.open = true;
  1641. // 查询已绑定的用户
  1642. this.loadBoundUsers(row.userId);
  1643. },
  1644. /** 查询已绑定的用户 */
  1645. loadBoundUsers(companyUserId) {
  1646. getBoundUsers(companyUserId).then(response => {
  1647. if (response.code === 200 && response.data) {
  1648. this.boundUsersList = Array.isArray(response.data) ? response.data : [response.data];
  1649. } else {
  1650. this.boundUsersList = [];
  1651. }
  1652. }).catch(() => {
  1653. this.boundUsersList = [];
  1654. });
  1655. },
  1656. /** 根据手机号码查询fs_user */
  1657. queryFsUserByPhone() {
  1658. if (!this.bindUserForm.phone) {
  1659. this.$message.warning('请输入手机号码');
  1660. return;
  1661. }
  1662. // 验证手机号码格式
  1663. const phonePattern = /^1[3|4|5|6|7|8|9][0-9]\d{8}$/;
  1664. if (!phonePattern.test(this.bindUserForm.phone)) {
  1665. this.$message.error('请输入正确的手机号码');
  1666. return;
  1667. }
  1668. this.bindUserLoading = true;
  1669. queryFsUserByPhone(this.bindUserForm.phone).then(response => {
  1670. this.bindUserLoading = false;
  1671. if (response.code === 200) {
  1672. if (response.data) {
  1673. // 如果返回的是单个对象,转换为数组
  1674. this.fsUserList = Array.isArray(response.data) ? response.data : [response.data];
  1675. if (this.fsUserList.length === 0) {
  1676. this.$message.info('未找到匹配的用户');
  1677. }
  1678. } else {
  1679. this.fsUserList = [];
  1680. this.$message.info('未找到匹配的用户');
  1681. }
  1682. } else {
  1683. this.fsUserList = [];
  1684. this.$message.error(response.msg || '查询失败');
  1685. }
  1686. }).catch(error => {
  1687. this.bindUserLoading = false;
  1688. this.fsUserList = [];
  1689. this.$message.error('查询失败');
  1690. });
  1691. },
  1692. /** 处理fs_user选择变化 */
  1693. handleFsUserSelectionChange(selection) {
  1694. this.selectedFsUserIds = selection.map(item => item.userId);
  1695. },
  1696. /** 提交绑定用户 */
  1697. submitBindUser() {
  1698. if (this.selectedFsUserIds.length === 0) {
  1699. this.$message.warning('请至少选择一个用户');
  1700. return;
  1701. }
  1702. const data = {
  1703. companyUserId: this.bindUserForm.companyUserId,
  1704. fsUserIds: this.selectedFsUserIds
  1705. };
  1706. batchBindCompanyUserId(data).then(response => {
  1707. if (response.code === 200) {
  1708. this.$message.success('绑定成功');
  1709. this.bindUserDialog.open = false;
  1710. this.getList();
  1711. } else {
  1712. this.$message.error(response.msg || '绑定失败');
  1713. }
  1714. }).catch(error => {
  1715. this.$message.error('绑定失败');
  1716. });
  1717. },
  1718. /** 重置绑定用户表单 */
  1719. resetBindUserForm() {
  1720. this.bindUserForm = {
  1721. phone: '',
  1722. companyUserId: null
  1723. };
  1724. this.fsUserList = [];
  1725. this.selectedFsUserIds = [];
  1726. this.boundUsersList = [];
  1727. this.bindUserLoading = false;
  1728. },
  1729. },
  1730. }
  1731. </script>