tenantIndex.vue 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383
  1. <template>
  2. <div class="app-container">
  3. <el-form
  4. :model="queryParams"
  5. ref="queryForm"
  6. size="small"
  7. :inline="true"
  8. v-show="showSearch"
  9. label-width="68px"
  10. >
  11. <el-form-item label="租户名称" prop="tenantName">
  12. <el-input
  13. v-model="queryParams.tenantName"
  14. placeholder="请输入租户名称"
  15. clearable
  16. @keyup.enter.native="handleQuery"
  17. />
  18. </el-form-item>
  19. <el-form-item label="租户编号" prop="tenantCode">
  20. <el-input
  21. v-model="queryParams.tenantCode"
  22. placeholder="请输入租户编号"
  23. clearable
  24. @keyup.enter.native="handleQuery"
  25. />
  26. </el-form-item>
  27. <el-form-item label="负责人" prop="owner">
  28. <el-input
  29. v-model="queryParams.owner"
  30. placeholder="请输入负责人"
  31. clearable
  32. @keyup.enter.native="handleQuery"
  33. />
  34. </el-form-item>
  35. <el-form-item label="联系方式" prop="contactInfo">
  36. <el-input
  37. v-model="queryParams.contactInfo"
  38. placeholder="请输入联系方式"
  39. clearable
  40. @keyup.enter.native="handleQuery"
  41. />
  42. </el-form-item>
  43. <el-form-item label="地址" prop="address">
  44. <el-input
  45. v-model="queryParams.address"
  46. placeholder="请输入地址"
  47. clearable
  48. @keyup.enter.native="handleQuery"
  49. />
  50. </el-form-item>
  51. <el-form-item>
  52. <el-button
  53. type="primary"
  54. icon="el-icon-search"
  55. size="mini"
  56. @click="handleQuery"
  57. >搜索
  58. </el-button>
  59. <el-button icon="el-icon-refresh" size="mini" @click="resetQuery"
  60. >重置
  61. </el-button>
  62. </el-form-item>
  63. </el-form>
  64. <el-row :gutter="10" class="mb8">
  65. <el-col :span="1.5">
  66. <el-button
  67. type="primary"
  68. plain
  69. icon="el-icon-plus"
  70. size="mini"
  71. @click="handleAdd"
  72. v-hasPermi="['system:tenant:add']"
  73. >新增
  74. </el-button>
  75. </el-col>
  76. <el-col :span="1.5">
  77. <el-button
  78. v-if="selection.length == 0"
  79. type="warning"
  80. plain
  81. icon="el-icon-download"
  82. size="mini"
  83. @click="handleExport"
  84. v-hasPermi="['system:tenant:export']"
  85. >导出
  86. </el-button>
  87. <ExcelDownLoad
  88. v-else
  89. :headerList="headerList"
  90. :fieldList="selection"
  91. :excelTitle="excelTitle"
  92. ></ExcelDownLoad>
  93. </el-col>
  94. <right-toolbar
  95. :showSearch.sync="showSearch"
  96. @queryTable="getList"
  97. ></right-toolbar>
  98. </el-row>
  99. <el-table
  100. :data="tenantList"
  101. style="width: 100%"
  102. row-key="tenantId"
  103. border
  104. lazy
  105. :load="load"
  106. :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
  107. >
  108. <el-table-column label="租户ID" align="center" prop="tenantId" />
  109. <el-table-column label="租户名称" align="center" prop="tenantName" />
  110. <el-table-column label="租户编号" align="center" prop="tenantCode" />
  111. <el-table-column label="负责人" align="center" prop="owner" />
  112. <el-table-column label="联系方式" align="center" prop="contactInfo" />
  113. <el-table-column label="地址" align="center" prop="address" />
  114. <el-table-column
  115. label="租户父级ID"
  116. align="center"
  117. prop="tenantParentId"
  118. />
  119. <el-table-column
  120. label="客户端访问地址"
  121. align="center"
  122. prop="tenantClientLoginUrl"
  123. />
  124. <el-table-column
  125. label="工具端访问地址"
  126. align="center"
  127. prop="tenantToolLoginUrl"
  128. />
  129. <el-table-column label="租户等级" align="center" prop="tenantGrade" />
  130. <el-table-column
  131. label="到期天数"
  132. align="center"
  133. prop="tenantExpirationTime"
  134. />
  135. <el-table-column
  136. label="操作"
  137. align="center"
  138. class-name="small-padding fixed-width"
  139. >
  140. <template slot-scope="scope">
  141. <el-dropdown>
  142. <el-button type="warning" plain size="small">
  143. 处理<i class="el-icon-arrow-down el-icon--right"></i>
  144. </el-button>
  145. <el-dropdown-menu slot="dropdown">
  146. <el-dropdown-item>
  147. <el-button
  148. size="mini"
  149. type="text"
  150. icon="el-icon-edit"
  151. @click="handleUpdate(scope.row)"
  152. v-hasPermi="['system:tenant:edit']"
  153. >修改
  154. </el-button>
  155. </el-dropdown-item>
  156. <el-dropdown-item>
  157. <el-button
  158. size="mini"
  159. type="text"
  160. icon="el-icon-delete"
  161. @click="handleDelete(scope.row)"
  162. v-hasPermi="['system:tenant:remove']"
  163. >删除
  164. </el-button>
  165. </el-dropdown-item>
  166. <el-dropdown-item>
  167. <el-button
  168. size="mini"
  169. type="text"
  170. icon="el-icon-position"
  171. @click="bindDatasource(scope.row)"
  172. v-show="scope.row.datasourceId == null"
  173. >绑定数据源
  174. </el-button>
  175. </el-dropdown-item>
  176. <el-dropdown-item>
  177. <el-button
  178. size="mini"
  179. type="text"
  180. icon="el-icon-s-custom"
  181. @click="openTenantExpirationTime(scope.row)"
  182. v-hasPermi="['system:tenant:remove']"
  183. >激活租户
  184. </el-button>
  185. </el-dropdown-item>
  186. <el-dropdown-item>
  187. <el-button
  188. size="mini"
  189. type="text"
  190. icon="el-icon-s-open"
  191. @click="openLoginConfig(scope.row)"
  192. v-hasPermi="['system:tenant:remove']"
  193. >配置登录页
  194. </el-button>
  195. </el-dropdown-item>
  196. </el-dropdown-menu>
  197. </el-dropdown>
  198. </template>
  199. </el-table-column>
  200. </el-table>
  201. <!-- <el-table
  202. v-loading="loading"
  203. :data="tenantList"
  204. @selection-change="handleSelectionChange"
  205. >
  206. <el-table-column type="selection" width="55" align="center" />
  207. <el-table-column label="租户ID" align="center" prop="tenantId" />
  208. <el-table-column label="租户名称" align="center" prop="tenantName" />
  209. <el-table-column label="租户编号" align="center" prop="tenantCode" />
  210. <el-table-column label="负责人" align="center" prop="owner" />
  211. <el-table-column label="联系方式" align="center" prop="contactInfo" />
  212. <el-table-column label="地址" align="center" prop="address" />
  213. <el-table-column
  214. label="租户父级ID"
  215. align="center"
  216. prop="tenantParentId"
  217. />
  218. <el-table-column
  219. label="客户端访问地址"
  220. align="center"
  221. prop="tenantClientLoginUrl"
  222. />
  223. <el-table-column
  224. label="工具端访问地址"
  225. align="center"
  226. prop="tenantToolLoginUrl"
  227. />
  228. <el-table-column label="租户等级" align="center" prop="tenantGrade" />
  229. <el-table-column
  230. label="到期天数"
  231. align="center"
  232. prop="tenantExpirationTime"
  233. />
  234. <el-table-column
  235. label="操作"
  236. align="center"
  237. class-name="small-padding fixed-width"
  238. >
  239. <template slot-scope="scope">
  240. <el-dropdown>
  241. <el-button type="warning" plain size="small">
  242. 处理<i class="el-icon-arrow-down el-icon--right"></i>
  243. </el-button>
  244. <el-dropdown-menu slot="dropdown">
  245. <el-dropdown-item>
  246. <el-button
  247. size="mini"
  248. type="text"
  249. icon="el-icon-edit"
  250. @click="handleUpdate(scope.row)"
  251. v-hasPermi="['system:tenant:edit']"
  252. >修改
  253. </el-button>
  254. </el-dropdown-item>
  255. <el-dropdown-item>
  256. <el-button
  257. size="mini"
  258. type="text"
  259. icon="el-icon-delete"
  260. @click="handleDelete(scope.row)"
  261. v-hasPermi="['system:tenant:remove']"
  262. >删除
  263. </el-button>
  264. </el-dropdown-item>
  265. <el-dropdown-item>
  266. <el-button
  267. size="mini"
  268. type="text"
  269. icon="el-icon-position"
  270. @click="bindDatasource(scope.row)"
  271. v-show="scope.row.datasourceId == null"
  272. >绑定数据源
  273. </el-button>
  274. </el-dropdown-item>
  275. <el-dropdown-item>
  276. <el-button
  277. size="mini"
  278. type="text"
  279. icon="el-icon-s-custom"
  280. @click="openTenantExpirationTime(scope.row)"
  281. v-hasPermi="['system:tenant:remove']"
  282. >激活租户
  283. </el-button>
  284. </el-dropdown-item>
  285. <el-dropdown-item>
  286. <el-button
  287. size="mini"
  288. type="text"
  289. icon="el-icon-s-open"
  290. @click="openLoginConfig(scope.row)"
  291. v-hasPermi="['system:tenant:remove']"
  292. >配置登录页
  293. </el-button>
  294. </el-dropdown-item>
  295. </el-dropdown-menu>
  296. </el-dropdown>
  297. </template>
  298. </el-table-column>
  299. </el-table> -->
  300. <pagination
  301. v-show="total > 0"
  302. :total="total"
  303. :page.sync="queryParams.pageNum"
  304. :limit.sync="queryParams.pageSize"
  305. @pagination="getList"
  306. />
  307. <!-- 添加或修改租户信息对话框 -->
  308. <el-dialog :title="title" :visible.sync="open" width="800px" append-to-body>
  309. <el-form ref="form" :model="form" :rules="rules" label-width="120px">
  310. <el-form-item label="选择上级租户" prop="tenantParentId">
  311. <el-cascader
  312. v-model="form.tenantParentId"
  313. :options="tenantAllList"
  314. :props="{
  315. checkStrictly: true,
  316. label: 'tenantName',
  317. value: 'tenantId',
  318. }"
  319. clearable
  320. ></el-cascader>
  321. </el-form-item>
  322. <el-form-item label="租户类型" prop="tenantProfession" >
  323. <el-select v-model="form.tenantProfession" placeholder="请选择租户类型" style="width: 250px">
  324. <el-option
  325. v-for="item in tenantProfessionList"
  326. :key="item.dictValue"
  327. :label="item.dictLabel"
  328. :value="item.dictValue"
  329. >
  330. </el-option>
  331. </el-select>
  332. </el-form-item>
  333. <el-form-item label="租户名称" prop="tenantName">
  334. <el-input v-model="form.tenantName" placeholder="请输入租户名称" />
  335. </el-form-item>
  336. <el-form-item label="租户编号" prop="tenantCode">
  337. <el-input v-model="form.tenantCode" placeholder="请输入租户编号" />
  338. </el-form-item>
  339. <el-form-item label="负责人" prop="owner">
  340. <el-input v-model="form.owner" placeholder="请输入负责人" />
  341. </el-form-item>
  342. <el-form-item label="联系方式" prop="contactInfo">
  343. <el-input v-model="form.contactInfo" placeholder="请输入联系方式" />
  344. </el-form-item>
  345. <el-form-item label="地址" prop="address">
  346. <el-input v-model="form.address" placeholder="请输入地址" />
  347. </el-form-item>
  348. <el-form-item label="客户端访问地址" prop="tenantClientLoginUrl">
  349. <el-input
  350. v-model="form.tenantClientLoginUrl"
  351. placeholder="请输入客户端访问地址"
  352. />
  353. </el-form-item>
  354. <el-form-item label="工具端访问地址" prop="tenantToolLoginUrl">
  355. <el-input
  356. v-model="form.tenantToolLoginUrl"
  357. placeholder="请输入工具端访问地址"
  358. />
  359. </el-form-item>
  360. <el-form-item label="租户等级" prop="tenantGrade">
  361. <el-input v-model="form.tenantGrade" placeholder="请输入租户等级" />
  362. </el-form-item>
  363. </el-form>
  364. <div slot="footer" class="dialog-footer">
  365. <el-button type="primary" @click="submitForm">确 定</el-button>
  366. <el-button @click="cancel">取 消</el-button>
  367. </div>
  368. </el-dialog>
  369. <!-- 添加或修改数据源信息对话框 -->
  370. <el-dialog
  371. :title="dataSourceTitle"
  372. :visible.sync="dataSourceOpen"
  373. width="500px"
  374. append-to-body
  375. class="loadingClass"
  376. >
  377. <el-radio-group
  378. v-model="dataSourceType"
  379. class="mb5"
  380. @input="dataSourceTypeChange"
  381. >
  382. <el-radio-button :label="true">公网</el-radio-button>
  383. <el-radio-button :label="false">内网</el-radio-button>
  384. </el-radio-group>
  385. <el-form
  386. ref="dataSourceForm"
  387. :model="dataSourceForm"
  388. :rules="dataSourceFormRules"
  389. label-width="120px"
  390. >
  391. <el-form-item label="数据源类型" prop="databaseType">
  392. <el-select
  393. v-model="dataSourceForm.databaseType"
  394. :placeholder="palcemsg"
  395. @change="selecthandle"
  396. :disabled="dataSourceType"
  397. >
  398. <el-option
  399. v-for="item in dict.type.datasource_type"
  400. :key="item.value"
  401. :label="item.label"
  402. :value="item.value"
  403. ></el-option>
  404. </el-select>
  405. </el-form-item>
  406. <el-form-item label="数据库名称" prop="databaseName">
  407. <el-input
  408. v-model="dataSourceForm.databaseName"
  409. placeholder="请输入数据库名称"
  410. />
  411. </el-form-item>
  412. <el-form-item label="租户管理员账号" prop="tenantAccount">
  413. <el-input
  414. v-model="dataSourceForm.tenantAccount"
  415. placeholder="请输入租户管理员账号"
  416. />
  417. </el-form-item>
  418. <!-- !dataSourceType -->
  419. <el-form-item
  420. label="数据库IP"
  421. v-show="!dataSourceType"
  422. prop="databaseIp"
  423. >
  424. <el-input
  425. v-model="dataSourceForm.databaseIp"
  426. placeholder="请输数据库IP"
  427. />
  428. </el-form-item>
  429. <el-form-item label="用户名" v-show="!dataSourceType" prop="username">
  430. <el-input
  431. v-model="dataSourceForm.username"
  432. placeholder="请输入用户名"
  433. />
  434. </el-form-item>
  435. <el-form-item label="密码" v-show="!dataSourceType" prop="password">
  436. <el-input
  437. v-model="dataSourceForm.password"
  438. placeholder="请输入密码"
  439. />
  440. </el-form-item>
  441. <el-form-item label="端口号" v-show="!dataSourceType" prop="portNumber">
  442. <el-input
  443. v-model="dataSourceForm.portNumber"
  444. placeholder="请输入端口号"
  445. />
  446. </el-form-item>
  447. </el-form>
  448. <div slot="footer" class="dialog-footer">
  449. <el-button
  450. type="primary"
  451. @click="submitForm1"
  452. :disabled="dialogLoading"
  453. :loading="dialogLoading"
  454. >{{ dialogLoading ? "绑定中" : "确 定" }}
  455. </el-button>
  456. <el-button @click="cancel1">取 消</el-button>
  457. </div>
  458. </el-dialog>
  459. <!-- 激活租户弹出层-->
  460. <el-dialog
  461. title="激活租户"
  462. :visible.sync="tenantExpirationTimeOpen"
  463. width="500px"
  464. append-to-body
  465. >
  466. <el-form
  467. ref="tenantExpirationTimeFrom"
  468. :model="tenantExpirationTimeFrom"
  469. :rules="rulesTenantExpirationTime"
  470. label-width="80px"
  471. >
  472. <el-form-item
  473. label="激活租户"
  474. prop="tenantExpirationTime"
  475. label-width="110px"
  476. >
  477. <el-input
  478. v-model="tenantExpirationTimeFrom.tenantExpirationTime"
  479. placeholder="请输入激活码"
  480. />
  481. </el-form-item>
  482. <el-form-item class="btn">
  483. <el-button
  484. type="primary"
  485. @click="activationOperationMethod('tenantExpirationTimeFrom')"
  486. >确 定
  487. </el-button>
  488. <el-button @click="tanentCancel">取 消</el-button>
  489. </el-form-item>
  490. </el-form>
  491. </el-dialog>
  492. <!-- 登录页面配置信息列表 -->
  493. <el-dialog
  494. title="配置登录页"
  495. width="800px"
  496. :visible.sync="loginOpen"
  497. append-to-body
  498. >
  499. <el-form
  500. ref="loginFormRef"
  501. :model="loginForm"
  502. :inline="true"
  503. :rules="rules"
  504. label-width="80px"
  505. >
  506. <el-form-item prop="loginPageNumber">
  507. <span slot="label">
  508. <el-tooltip
  509. content="请在登录时的url后拼接参数:tenantId={编号}"
  510. placement="top"
  511. >
  512. <i class="el-icon-question"></i>
  513. </el-tooltip>
  514. 编号:
  515. </span>
  516. <el-input
  517. v-model="loginForm.loginPageNumber"
  518. placeholder="请输入登录页面编号"
  519. disabled
  520. />
  521. </el-form-item>
  522. <!-- <el-col :span="8"> -->
  523. <el-form-item label="标题:" prop="loginPageTitle">
  524. <el-input
  525. v-model="loginForm.loginPageTitle"
  526. placeholder="请输入登录页面标题"
  527. />
  528. </el-form-item>
  529. <!-- </el-col> -->
  530. <!-- <el-col :span="8"> -->
  531. <el-form-item label="描述:" prop="loginPageDescription">
  532. <span slot="label">
  533. <el-tooltip
  534. content="推荐长度为8个汉字,可使用<br/>换行"
  535. placement="top"
  536. >
  537. <i class="el-icon-question"></i>
  538. </el-tooltip>
  539. 描述:
  540. </span>
  541. <el-input
  542. v-model="loginForm.loginPageDescription"
  543. type="textarea"
  544. placeholder="请输入内容"
  545. />
  546. </el-form-item>
  547. <!-- </el-col>
  548. <el-col :span="8"> -->
  549. <el-form-item label="窗口标题:" prop="windowTitle">
  550. <el-input
  551. v-model="loginForm.windowTitle"
  552. placeholder="请输入窗口标题"
  553. />
  554. </el-form-item>
  555. <!-- </el-col> -->
  556. <!-- <el-col :span="8"> -->
  557. <el-form-item prop="loginPageLogo">
  558. <span slot="label">
  559. <el-tooltip content="推荐图片大小为194*64px" placement="top">
  560. <i class="el-icon-question"></i>
  561. </el-tooltip>
  562. logo:
  563. </span>
  564. <image-upload :limit="1" v-model="loginForm.loginPageLogo" />
  565. </el-form-item>
  566. <!-- </el-col> -->
  567. <!-- <el-col :span="8"> -->
  568. <el-form-item prop="loginPageBackgroundImage">
  569. <span slot="label">
  570. <el-tooltip content="推荐图片大小为1400*900px" placement="top">
  571. <i class="el-icon-question"></i>
  572. </el-tooltip>
  573. 背景图:
  574. </span>
  575. <image-upload
  576. :limit="1"
  577. v-model="loginForm.loginPageBackgroundImage"
  578. />
  579. </el-form-item>
  580. <!-- </el-col> -->
  581. <!-- <el-col :span="8"> -->
  582. <!-- <el-form-item label="窗口logo:" prop="windowLogo">
  583. <image-upload
  584. :fileType="['png']"
  585. :limit="1"
  586. :uploadUrl="'/common/uploadAndConvert'"
  587. v-model="loginForm.windowLogo"
  588. />
  589. </el-form-item> -->
  590. <!-- </el-col> -->
  591. </el-form>
  592. <div slot="footer" class="dialog-footer">
  593. <el-button type="primary" @click="submitLoginForm">确 定</el-button>
  594. <el-button @click="cancelLoginForm">取 消</el-button>
  595. </div>
  596. </el-dialog>
  597. </div>
  598. </template>
  599. <script>
  600. import {
  601. listTenant,
  602. getTenant,
  603. delTenant,
  604. addTenant,
  605. updateTenant,
  606. bindDatasource,
  607. selectAllUser,
  608. createTenant,
  609. initTenantMenuData,
  610. activationOperation,
  611. getTenantChildrenInfo,
  612. getTenantAllList,
  613. tenantTree,
  614. } from "@/api/system/tenant";
  615. import { getDataSourceInfo, insertDataSource } from "@/api/system/data";
  616. import { getDicts } from "@/api/system/dict/data";
  617. import {
  618. listConfiguration,
  619. getConfiguration,
  620. delConfiguration,
  621. addConfiguration,
  622. updateConfiguration,
  623. } from "@/api/system/configuration";
  624. import { servicesLoading } from "@/utils/zkqy";
  625. import { getIsExistUser } from "@/api/system/user";
  626. import ExcelDownLoad from "@/components/ExcelDownLoad/index.vue";
  627. import { mapState } from "vuex";
  628. export default {
  629. name: "Tenant",
  630. dicts: [
  631. "datasource_type",
  632. "sqlserver_connection_information",
  633. "mysql_connection_information",
  634. "dm_connection_information",
  635. "orcale_connection_information",
  636. "system_login_url",
  637. ],
  638. components: {
  639. ExcelDownLoad,
  640. },
  641. data() {
  642. return {
  643. tenantProfessionList:[],
  644. tenantAllList: [],
  645. // 登录页面数据
  646. isEdit: false,
  647. loginOpen: false,
  648. loginForm: {
  649. loginPageNumber: "",
  650. loginPageTitle: "",
  651. loginPageDescription: "",
  652. loginPageLogo: "",
  653. loginPageBackgroundImage: "",
  654. windowTitle: "",
  655. windowLogo: "",
  656. tenantId: "",
  657. },
  658. // 前端导出数据
  659. selection: [],
  660. headerList: {
  661. 租户名称: "tenantName",
  662. 租户编号: "tenantCode",
  663. 负责人: "owner",
  664. 联系方式: "contactInfo",
  665. 地址: "address",
  666. 是否删除: "isDel",
  667. },
  668. excelTitle: "tenant",
  669. // 弹窗的加载提示
  670. dialogLoading: false,
  671. // 遮罩层
  672. loading: true,
  673. // 选中数组
  674. ids: [],
  675. // 非单个禁用
  676. single: true,
  677. // 非多个禁用
  678. multiple: true,
  679. // 显示搜索条件
  680. showSearch: true,
  681. // 总条数
  682. total: 0,
  683. // 租户信息表格数据
  684. tenantList: [],
  685. // 弹出层标题
  686. title: "",
  687. // 是否显示弹出层
  688. open: false,
  689. // 所有用户信息
  690. allUser: [],
  691. // 查询参数
  692. queryParams: {
  693. pageNum: 1,
  694. pageSize: 10,
  695. tenantName: null,
  696. tenantCode: null,
  697. owner: null,
  698. contactInfo: null,
  699. address: null,
  700. },
  701. // 当前编辑租户的信息
  702. currentTenantInfo: {},
  703. // 表单参数
  704. form: {},
  705. // 表单校验
  706. rules: {
  707. tenantName: [
  708. { required: true, message: "租户名称不能为空", trigger: "blur" },
  709. ],
  710. tenantCode: [
  711. { required: true, message: "租户编号不能为空", trigger: "blur" },
  712. ],
  713. tenantParentId: [
  714. { required: true, message: "请选择上级租户", trigger: "blur" },
  715. ],
  716. },
  717. //数据源表单参数
  718. dataSourceType: true, //true:公网 false:内网
  719. dataSourceForm: {
  720. databaseType: "",
  721. databaseName: "",
  722. tenantAccount: "",
  723. databaseIp: "",
  724. username: "",
  725. password: "",
  726. portNumber: "",
  727. },
  728. dataSourceTitle: "",
  729. dataSourceOpen: false,
  730. fromTenantId: null,
  731. dataSourceFormRules: {
  732. databaseType: [
  733. { required: true, message: "数据源类型不能为空", trigger: "change" },
  734. ],
  735. databaseName: [
  736. { required: true, message: "数据库名不能为空", trigger: "blur" },
  737. { validator: this.databaseNameValidator, trigger: "blur" },
  738. ],
  739. tenantAccount: [
  740. {
  741. required: true,
  742. message: "租户管理员账号不能为空",
  743. trigger: "change",
  744. },
  745. { validator: this.tenantAccountValidator, trigger: "blur" },
  746. ],
  747. databaseIp: [
  748. { required: true, message: "数据库IP不能为空", trigger: "blur" },
  749. ],
  750. username: [
  751. { required: true, message: "用户名不能为空", trigger: "blur" },
  752. ],
  753. password: [
  754. { required: true, message: "密码不能为空", trigger: "blur" },
  755. ],
  756. portNumber: [
  757. { required: true, message: "端口号不能为空", trigger: "blur" },
  758. ],
  759. },
  760. //租户激活码弹窗表单
  761. tenantExpirationTimeFrom: {
  762. tenantId: null,
  763. tenantExpirationTime: "",
  764. },
  765. //租户激活码弹窗标题
  766. tenantExpirationTimeOpen: false,
  767. //租户激活码规则验证
  768. rulesTenantExpirationTime: {
  769. tenantExpirationTime: [
  770. { required: true, message: "请输入租户激活码", trigger: "blur" },
  771. ],
  772. },
  773. currentPage: "",
  774. // 已存在的数据库名称
  775. databaseNameList: [],
  776. tableData1: [
  777. {
  778. id: 1,
  779. date: "2016-05-02",
  780. name: "王小虎",
  781. address: "上海市普陀区金沙江路 1518 弄",
  782. },
  783. {
  784. id: 2,
  785. date: "2016-05-04",
  786. name: "王小虎",
  787. address: "上海市普陀区金沙江路 1517 弄",
  788. },
  789. {
  790. id: 3,
  791. date: "2016-05-01",
  792. name: "王小虎",
  793. address: "上海市普陀区金沙江路 1519 弄",
  794. hasChildren: true,
  795. },
  796. {
  797. id: 4,
  798. date: "2016-05-03",
  799. name: "王小虎",
  800. address: "上海市普陀区金沙江路 1516 弄",
  801. },
  802. ],
  803. };
  804. },
  805. computed: {
  806. palcemsg() {
  807. return this.dataSourceType ? "mysql" : "请选择数据源类型";
  808. },
  809. ...mapState({
  810. userInfo: (state) => state,
  811. }),
  812. },
  813. created() {
  814. this.getList();
  815. // this.selectAllUser();
  816. this.getTenantTypeList();
  817. },
  818. methods: {
  819. load(tree, treeNode, resolve) {
  820. console.log(tree, treeNode, resolve);
  821. // 根据当前租户id查询子租户
  822. getTenantChildrenInfo(tree.tenantId).then((res) => {
  823. if (res.data != null) {
  824. resolve(res.data);
  825. } else {
  826. resolve({});
  827. }
  828. });
  829. },
  830. // 获取所有的租户类型,
  831. getTenantTypeList(){
  832. this.getDicts("tenant_profession").then(res=>{
  833. this.tenantProfessionList=res.data;
  834. })
  835. },
  836. // 查询所有平台所有租户
  837. getTenantAllList() {
  838. tenantTree().then((response) => {
  839. let tenantAllListOne = this.handleTree(
  840. response.data,
  841. "tenantId",
  842. "tenantParentId"
  843. );
  844. this.tenantAllList = [
  845. // { tenantId: 0, tenantName: "顶级租户" },
  846. ...tenantAllListOne,
  847. ];
  848. });
  849. },
  850. buildTree(data, parentId = null) {
  851. const children = data.filter((item) => item.tenantParentId === parentId);
  852. return children.map((child) => ({
  853. value: child.tenantId,
  854. label: child.tenantName,
  855. children: this.buildTree(data, child.tenantId), // 将 child.tenant_id 作为下一层的 parentId
  856. }));
  857. },
  858. transformTenantsToCascaderOptions(tenants) {
  859. console.log(tenants);
  860. const options = [];
  861. const map = {}; // 用于存储每个tenant的引用,以便后续添加children
  862. tenants.forEach((tenant) => {
  863. const { tenantId, tenantName, tenantParentId } = tenant;
  864. const option = {
  865. value: tenantId,
  866. label: tenantName,
  867. children: [], // 初始化children数组
  868. };
  869. if (tenantParentId === null) {
  870. // 如果没有父级,说明是顶级租户,直接添加到options中
  871. options.push(option);
  872. } else {
  873. // 如果有父级,则先查找父级租户在map中的引用,并添加到其children数组中
  874. if (!map[tenantParentId]) {
  875. // 如果父级租户还没被处理过,先创建一个空的引用
  876. map[tenantParentId] = { children: [] };
  877. }
  878. map[tenantParentId].children.push(option);
  879. }
  880. // 将当前租户添加到map中,方便后续查找
  881. map[tenantId] = option;
  882. });
  883. // 遍历map,将顶级租户的children填充完整
  884. Object.values(map).forEach((option) => {
  885. if (!options.includes(option)) {
  886. // 如果这个选项不是顶级租户,则将其添加到某个顶级租户的children中
  887. const parentOption = options.find((o) => o.children.includes(option));
  888. if (parentOption) {
  889. parentOption.children.push(option);
  890. }
  891. }
  892. });
  893. console.log(options);
  894. return options;
  895. },
  896. // 提交登录页配置数据
  897. submitLoginForm() {
  898. this.$refs.loginFormRef?.validate(async (valid) => {
  899. if (valid) {
  900. console.log(this.loginForm);
  901. let res = {},
  902. msg = "";
  903. if (this.isEdit) {
  904. res = await updateConfiguration(this.loginForm);
  905. msg = "修改";
  906. } else {
  907. res = await addConfiguration(this.loginForm);
  908. msg = "保存";
  909. }
  910. if (res.code == 200) {
  911. this.$message.success(`${msg}成功`);
  912. this.loginOpen = false;
  913. } else {
  914. this.$message.error(`${msg}失败,请检查网络`);
  915. }
  916. } else {
  917. console.log(`${msg}失败,请检查网络`);
  918. return false;
  919. }
  920. });
  921. },
  922. // 取消登录页配置
  923. cancelLoginForm() {
  924. this.loginOpen = false;
  925. },
  926. // 编辑租户登录页配置
  927. async openLoginConfig(row) {
  928. try {
  929. let res = await getConfiguration(row.tenantId);
  930. if (res.code == 200) {
  931. if (res.data) {
  932. this.loginForm = res.data;
  933. this.isEdit = true;
  934. } else {
  935. this.resetloginForm();
  936. this.isEdit = false;
  937. }
  938. // 目前一个租户只能有一个配置项故使用租户唯一编码
  939. this.loginForm.loginPageNumber = row.tenantCode;
  940. this.loginForm.tenantId = row.tenantId;
  941. this.loginOpen = true;
  942. } else {
  943. this.$message.error("网络异常,请稍后再试");
  944. }
  945. } catch (error) {}
  946. },
  947. // 获取所用用户名,作校验用
  948. async selectAllUser() {
  949. let res = await selectAllUser();
  950. if (res.code == 200) {
  951. this.allUser = res.data;
  952. } else {
  953. console.log(res.msg);
  954. }
  955. },
  956. // 重置login配置表单数据
  957. resetloginForm() {
  958. this.loginForm = {
  959. loginPageNumber: "",
  960. loginPageTitle: "",
  961. loginPageDescription: "",
  962. loginPageLogo: "",
  963. loginPageBackgroundImage: "",
  964. windowTitle: "",
  965. windowLogo: "",
  966. tenantId: "",
  967. };
  968. },
  969. // 租户名自定义校验规则
  970. async tenantAccountValidator(rule, value, callback) {
  971. // let isRepeat = this.allUser.filter((item) => item.userName == value);
  972. // if (isRepeat.length !== 0) {
  973. // callback(new Error("租户账号重复"));
  974. // } else {
  975. // callback();
  976. // }
  977. if (value) {
  978. await getIsExistUser({ userName: value }).then((res) => {
  979. if (res.code == 200) {
  980. if (res.data) {
  981. callback();
  982. } else {
  983. callback(new Error("租户管理员账号已存在"));
  984. }
  985. } else {
  986. callback(new Error("租户管理员账号校验失败,请重新输入"));
  987. }
  988. });
  989. }
  990. callback();
  991. },
  992. // 数据库名自定义校验规则--请求后端校验
  993. // async databaseNameValidator(rule, value, callback) {
  994. // if (value) {
  995. // await getDataSourceInfo({ databaseName: value }).then((res) => {
  996. // if (res.code == 200) {
  997. // if (res.data) {
  998. // callback();
  999. // } else {
  1000. // callback(new Error("数据库名已存在"));
  1001. // }
  1002. // } else {
  1003. // callback(new Error("数据库名校验失败,请重新输入"));
  1004. // }
  1005. // });
  1006. // }
  1007. // },
  1008. // 数据库名称校验规则
  1009. databaseNameValidator(rule, value, callback) {
  1010. // 正则校验
  1011. let regex = /^[a-z][a-z0-9]*$/;
  1012. if (regex.test(value)) {
  1013. // callback(); // 输入内容符合规则
  1014. } else {
  1015. callback(new Error("只能包含小写字母和数字,且以小写字母开头"));
  1016. }
  1017. // 重名校验
  1018. let isRepeat = this.databaseNameList.filter((item) => item == value);
  1019. if (isRepeat.length !== 0) {
  1020. callback(new Error("数据库名重复"));
  1021. } else {
  1022. callback();
  1023. }
  1024. },
  1025. // 数据源类型改变回调
  1026. dataSourceTypeChange(type) {
  1027. this.$nextTick(() => {
  1028. this.$refs.dataSourceForm.resetFields();
  1029. this.dataSourceForm.databaseType = "mysql";
  1030. this.selecthandle("mysql");
  1031. });
  1032. },
  1033. handleOpe() {},
  1034. /** 查询租户信息列表 */
  1035. getList() {
  1036. this.loading = true;
  1037. this.currentPage = this.queryParams.pageNum;
  1038. this.queryParams.tenantParentId = this.userInfo.user.tenant.tenantId;
  1039. getTenantAllList(this.queryParams).then((response) => {
  1040. this.tenantList = response.rows;
  1041. this.tenantList.forEach((item) => {
  1042. item["hasChildren"] = true;
  1043. });
  1044. this.total = response.total;
  1045. this.loading = false;
  1046. });
  1047. },
  1048. // 取消按钮
  1049. cancel() {
  1050. this.open = false;
  1051. this.reset();
  1052. },
  1053. // 绑定数据源取消按钮
  1054. cancel1() {
  1055. this.dataSourceOpen = false;
  1056. this.reset1();
  1057. },
  1058. // 表单重置
  1059. reset() {
  1060. this.form = {
  1061. tenantParentId: null,
  1062. tenantId: null,
  1063. tenantName: null,
  1064. tenantCode: null,
  1065. owner: null,
  1066. contactInfo: null,
  1067. address: null,
  1068. createBy: null,
  1069. createTime: null,
  1070. };
  1071. this.resetForm("form");
  1072. },
  1073. // 表单重置
  1074. reset1() {
  1075. this.dataSourceType = true;
  1076. this.dataSourceForm = {
  1077. id: null,
  1078. databaseName: null,
  1079. databaseIp: null,
  1080. tenantAccount: "",
  1081. username: null,
  1082. password: null,
  1083. portNumber: null,
  1084. databaseType: "mysql",
  1085. };
  1086. // this.resetForm("dataSourceForm");
  1087. },
  1088. /** 搜索按钮操作 */
  1089. handleQuery() {
  1090. this.queryParams.pageNum = 1;
  1091. this.getList();
  1092. },
  1093. /** 重置按钮操作 */
  1094. resetQuery() {
  1095. this.resetForm("queryForm");
  1096. this.handleQuery();
  1097. },
  1098. // 多选框选中数据
  1099. handleSelectionChange(selection) {
  1100. this.selection = selection;
  1101. this.ids = selection.map((item) => item.tenantId);
  1102. this.single = selection.length !== 1;
  1103. this.multiple = !selection.length;
  1104. },
  1105. /** 新增按钮操作 */
  1106. handleAdd() {
  1107. this.reset();
  1108. this.getTenantAllList();
  1109. this.open = true;
  1110. this.title = "添加租户信息";
  1111. },
  1112. /** 修改按钮操作 */
  1113. handleUpdate(row) {
  1114. this.reset();
  1115. this.getTenantAllList();
  1116. tenantTree().then((response) => {
  1117. let tenantAllListOne = this.handleTree(
  1118. response.data,
  1119. "tenantId",
  1120. "tenantParentId"
  1121. );
  1122. console.log("1h")
  1123. this.tenantAllList = [
  1124. // { tenantId: 0, tenantName: "顶级租户" },
  1125. ...tenantAllListOne,
  1126. ];
  1127. //先拿到当前租户的
  1128. const tenantId = row.tenantId || this.ids;
  1129. getTenant(tenantId).then((response) => {
  1130. console.log("5h")
  1131. response.data.tenantParentId=parseInt(response.data.tenantParentId)
  1132. this.form = response.data;
  1133. this.open = true;
  1134. this.title = "修改租户信息";
  1135. });
  1136. });
  1137. },
  1138. /** 绑定数据源按钮操作 */
  1139. bindDatasource(row) {
  1140. //当前行租户信息
  1141. this.currentTenantInfo = row;
  1142. this.reset1();
  1143. this.dialogLoading = false;
  1144. this.dataSourceOpen = true;
  1145. this.dataSourceTitle = row.tenantName + "配置数据库";
  1146. this.fromTenantId = row.tenantId;
  1147. this.dataSourceTypeChange();
  1148. // const tenantId = row.tenantId || this.ids;
  1149. // getTenant(tenantId).then((response) => {
  1150. // this.form = response.data;
  1151. // this.open = true;
  1152. // this.title = "修改租户信息";
  1153. // });
  1154. },
  1155. /** 提交按钮 */
  1156. submitForm() {
  1157. console.log("租户信息")
  1158. console.log("租户地址信息:", this.dict.type.system_login_url);
  1159. if (this.form.tenantParentId.length >= 0) {
  1160. // 处理当前租户的上级租户id
  1161. this.form.tenantParentId =
  1162. this.form.tenantParentId[this.form.tenantParentId.length - 1] !=
  1163. undefined
  1164. ? this.form.tenantParentId[this.form.tenantParentId.length - 1]
  1165. : "";
  1166. }
  1167. this.form.tenantClientLoginUrl = this.dict.type.system_login_url
  1168. .find((item) => item.label == "client_login_url")
  1169. ?.value.replace("#{val}", this.form.tenantCode);
  1170. this.form.tenantToolLoginUrl = this.dict.type.system_login_url
  1171. .find((item) => item.label == "crm_login_url")
  1172. ?.value.replace("#{val}", this.form.tenantCode);
  1173. this.$refs["form"].validate((valid) => {
  1174. if (valid) {
  1175. if (this.form.tenantId != null) {
  1176. updateTenant(this.form).then((response) => {
  1177. this.$modal.msgSuccess("修改成功");
  1178. this.open = false;
  1179. this.getList();
  1180. });
  1181. } else {
  1182. addTenant(this.form).then((response) => {
  1183. this.$modal.msgSuccess("新增成功");
  1184. this.open = false;
  1185. this.getList();
  1186. });
  1187. }
  1188. }
  1189. this.reset();
  1190. });
  1191. },
  1192. /** 提交按钮 */
  1193. submitForm1() {
  1194. if (this.dialogLoading) return;
  1195. this.dialogLoading = true;
  1196. this.$refs["dataSourceForm"].validate((valid) => {
  1197. if (valid) {
  1198. // const loading = servicesLoading(
  1199. // ".loadingClass",
  1200. // "正在绑定数据源",
  1201. // true
  1202. // );
  1203. if (this.dataSourceForm.id != null) {
  1204. // bindDatasource(this.dataSourceForm).then((response) => {
  1205. // this.$modal.msgSuccess("修改成功");
  1206. // this.dataSourceOpen = false;
  1207. // this.getList();
  1208. // });
  1209. this.dialogLoading = false;
  1210. } else {
  1211. let query = {
  1212. tenantId: this.fromTenantId,
  1213. dataSource: this.dataSourceForm,
  1214. };
  1215. bindDatasource(query)
  1216. .then((response) => {
  1217. if (response.code == 200) {
  1218. let data = {
  1219. userName: this.dataSourceForm.tenantAccount,
  1220. nickName: this.currentTenantInfo.tenantName,
  1221. userType: "01",
  1222. tenantId: this.currentTenantInfo.tenantId,
  1223. password: "123456",
  1224. };
  1225. createTenant(data)
  1226. .then(async (res) => {
  1227. if (res.code == 200) {
  1228. let resp = await initTenantMenuData(
  1229. this.currentTenantInfo.tenantId
  1230. );
  1231. if ((resp.code = 200)) {
  1232. this.$modal.msgSuccess("新增成功");
  1233. this.dataSourceOpen = false;
  1234. this.getList();
  1235. }
  1236. }
  1237. })
  1238. .finally(() => {
  1239. this.dialogLoading = false;
  1240. });
  1241. }
  1242. })
  1243. .finally(() => {
  1244. this.dialogLoading = false;
  1245. });
  1246. }
  1247. }
  1248. });
  1249. },
  1250. /** 删除按钮操作 */
  1251. handleDelete(row) {
  1252. const tenantIds = row.tenantId || this.ids;
  1253. this.$modal
  1254. .confirm('是否确认删除租户信息编号为"' + tenantIds + '"的数据项?')
  1255. .then(function () {
  1256. return delTenant(tenantIds);
  1257. })
  1258. .then(() => {
  1259. this.getList();
  1260. this.$modal.msgSuccess("删除成功");
  1261. })
  1262. .catch(() => {});
  1263. },
  1264. /** 导出按钮操作 */
  1265. handleExport() {
  1266. this.download(
  1267. "system/tenant/export",
  1268. {
  1269. ...this.queryParams,
  1270. },
  1271. `tenant_${new Date().getTime()}.xlsx`
  1272. );
  1273. },
  1274. /**
  1275. * 选择数据源校验名称
  1276. */
  1277. selecthandle(row) {
  1278. let sql = {
  1279. sqlserver: "sqlserver_connection_information",
  1280. mysql: "mysql_connection_information",
  1281. dm: "dm_connection_information",
  1282. oracle: "oracle_connection_information",
  1283. };
  1284. let qar = {};
  1285. this.dict.type[sql[row]].forEach((item) => {
  1286. qar[item.label] = item.value;
  1287. });
  1288. if (this.dataSourceType) {
  1289. let { databaseIp, password, portNumber, username } = qar;
  1290. Object.assign(this.dataSourceForm, {
  1291. databaseIp,
  1292. password,
  1293. portNumber,
  1294. username,
  1295. });
  1296. }
  1297. getDataSourceInfo(qar).then((res) => {
  1298. // console.log(res);
  1299. this.databaseNameList = res.data;
  1300. });
  1301. },
  1302. handleTest() {
  1303. let formdata = {
  1304. databaseType: "mysql",
  1305. databaseName: "test1111",
  1306. databaseIp: "127.0.0.1",
  1307. username: "testname",
  1308. password: "123123",
  1309. portNumber: "3306",
  1310. };
  1311. insertDataSource(formdata).then((res) => {
  1312. console.log(res);
  1313. });
  1314. },
  1315. //重置租户激活码表单
  1316. restTenantExpirationTime() {
  1317. this.tenantExpirationTimeFrom = {
  1318. tenantId: null,
  1319. tenantExpirationTime: "",
  1320. };
  1321. this.resetForm("tenantExpirationTimeFrom");
  1322. },
  1323. /**打开激活码弹窗*/
  1324. openTenantExpirationTime(row) {
  1325. // this.reset();
  1326. const tenantId = row.tenantId || this.ids;
  1327. this.tenantExpirationTimeFrom.tenantId = row.tenantId;
  1328. this.tenantExpirationTimeOpen = true;
  1329. // this.title="激活租户";
  1330. },
  1331. /**激活租户操作*/
  1332. activationOperationMethod(form) {
  1333. this.$refs[form].validate(async (valid) => {
  1334. if (valid) {
  1335. let response = await activationOperation(
  1336. this.tenantExpirationTimeFrom
  1337. );
  1338. if (response.code == 200) {
  1339. this.$message.success("激活成功");
  1340. //重新刷新列表
  1341. this.getList();
  1342. } else {
  1343. this.$message.error("激活失败");
  1344. }
  1345. this.tenantExpirationTimeOpen = false;
  1346. this.tenantExpirationTimeFrom = {
  1347. tenantId: null,
  1348. tenantExpirationTime: null,
  1349. };
  1350. }
  1351. });
  1352. },
  1353. // 激活租户对话框取消按钮
  1354. tanentCancel() {
  1355. this.tenantExpirationTimeOpen = false;
  1356. this.tenantExpirationTimeFrom = {
  1357. tenantId: null,
  1358. tenantExpirationTime: null,
  1359. };
  1360. },
  1361. },
  1362. };
  1363. </script>