tenantIndex.vue 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341
  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="80px">
  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="tenantName">
  323. <el-input v-model="form.tenantName" placeholder="请输入租户名称" />
  324. </el-form-item>
  325. <el-form-item label="租户编号" prop="tenantCode">
  326. <el-input v-model="form.tenantCode" placeholder="请输入租户编号" />
  327. </el-form-item>
  328. <el-form-item label="负责人" prop="owner">
  329. <el-input v-model="form.owner" placeholder="请输入负责人" />
  330. </el-form-item>
  331. <el-form-item label="联系方式" prop="contactInfo">
  332. <el-input v-model="form.contactInfo" placeholder="请输入联系方式" />
  333. </el-form-item>
  334. <el-form-item label="地址" prop="address">
  335. <el-input v-model="form.address" placeholder="请输入地址" />
  336. </el-form-item>
  337. <el-form-item label="客户端访问地址" prop="tenantClientLoginUrl">
  338. <el-input
  339. v-model="form.tenantClientLoginUrl"
  340. placeholder="请输入地址"
  341. />
  342. </el-form-item>
  343. <el-form-item label="工具端访问地址" prop="tenantToolLoginUrl">
  344. <el-input
  345. v-model="form.tenantToolLoginUrl"
  346. placeholder="请输入地址"
  347. />
  348. </el-form-item>
  349. <el-form-item label="租户等级" prop="tenantGrade">
  350. <el-input v-model="form.tenantGrade" placeholder="请输入地址" />
  351. </el-form-item>
  352. </el-form>
  353. <div slot="footer" class="dialog-footer">
  354. <el-button type="primary" @click="submitForm">确 定</el-button>
  355. <el-button @click="cancel">取 消</el-button>
  356. </div>
  357. </el-dialog>
  358. <!-- 添加或修改数据源信息对话框 -->
  359. <el-dialog
  360. :title="dataSourceTitle"
  361. :visible.sync="dataSourceOpen"
  362. width="500px"
  363. append-to-body
  364. class="loadingClass"
  365. >
  366. <el-radio-group
  367. v-model="dataSourceType"
  368. class="mb5"
  369. @input="dataSourceTypeChange"
  370. >
  371. <el-radio-button :label="true">公网</el-radio-button>
  372. <el-radio-button :label="false">内网</el-radio-button>
  373. </el-radio-group>
  374. <el-form
  375. ref="dataSourceForm"
  376. :model="dataSourceForm"
  377. :rules="dataSourceFormRules"
  378. label-width="120px"
  379. >
  380. <el-form-item label="数据源类型" prop="databaseType">
  381. <el-select
  382. v-model="dataSourceForm.databaseType"
  383. :placeholder="palcemsg"
  384. @change="selecthandle"
  385. :disabled="dataSourceType"
  386. >
  387. <el-option
  388. v-for="item in dict.type.datasource_type"
  389. :key="item.value"
  390. :label="item.label"
  391. :value="item.value"
  392. ></el-option>
  393. </el-select>
  394. </el-form-item>
  395. <el-form-item label="数据库名称" prop="databaseName">
  396. <el-input
  397. v-model="dataSourceForm.databaseName"
  398. placeholder="请输入数据库名称"
  399. />
  400. </el-form-item>
  401. <el-form-item label="租户管理员账号" prop="tenantAccount">
  402. <el-input
  403. v-model="dataSourceForm.tenantAccount"
  404. placeholder="请输入租户管理员账号"
  405. />
  406. </el-form-item>
  407. <!-- !dataSourceType -->
  408. <el-form-item
  409. label="数据库IP"
  410. v-show="!dataSourceType"
  411. prop="databaseIp"
  412. >
  413. <el-input
  414. v-model="dataSourceForm.databaseIp"
  415. placeholder="请输数据库IP"
  416. />
  417. </el-form-item>
  418. <el-form-item label="用户名" v-show="!dataSourceType" prop="username">
  419. <el-input
  420. v-model="dataSourceForm.username"
  421. placeholder="请输入用户名"
  422. />
  423. </el-form-item>
  424. <el-form-item label="密码" v-show="!dataSourceType" prop="password">
  425. <el-input
  426. v-model="dataSourceForm.password"
  427. placeholder="请输入密码"
  428. />
  429. </el-form-item>
  430. <el-form-item label="端口号" v-show="!dataSourceType" prop="portNumber">
  431. <el-input
  432. v-model="dataSourceForm.portNumber"
  433. placeholder="请输入端口号"
  434. />
  435. </el-form-item>
  436. </el-form>
  437. <div slot="footer" class="dialog-footer">
  438. <el-button
  439. type="primary"
  440. @click="submitForm1"
  441. :disabled="dialogLoading"
  442. :loading="dialogLoading"
  443. >{{ dialogLoading ? "绑定中" : "确 定" }}
  444. </el-button>
  445. <el-button @click="cancel1">取 消</el-button>
  446. </div>
  447. </el-dialog>
  448. <!-- 激活租户弹出层-->
  449. <el-dialog
  450. title="激活租户"
  451. :visible.sync="tenantExpirationTimeOpen"
  452. width="500px"
  453. append-to-body
  454. >
  455. <el-form
  456. ref="tenantExpirationTimeFrom"
  457. :model="tenantExpirationTimeFrom"
  458. :rules="rulesTenantExpirationTime"
  459. label-width="80px"
  460. >
  461. <el-form-item
  462. label="激活租户"
  463. prop="tenantExpirationTime"
  464. label-width="110px"
  465. >
  466. <el-input
  467. v-model="tenantExpirationTimeFrom.tenantExpirationTime"
  468. placeholder="请输入激活码"
  469. />
  470. </el-form-item>
  471. <el-form-item class="btn">
  472. <el-button
  473. type="primary"
  474. @click="activationOperationMethod('tenantExpirationTimeFrom')"
  475. >确 定
  476. </el-button>
  477. <el-button @click="tanentCancel">取 消</el-button>
  478. </el-form-item>
  479. </el-form>
  480. </el-dialog>
  481. <!-- 登录页面配置信息列表 -->
  482. <el-dialog
  483. title="配置登录页"
  484. width="800px"
  485. :visible.sync="loginOpen"
  486. append-to-body
  487. >
  488. <el-form
  489. ref="loginFormRef"
  490. :model="loginForm"
  491. :inline="true"
  492. :rules="rules"
  493. label-width="80px"
  494. >
  495. <el-form-item prop="loginPageNumber">
  496. <span slot="label">
  497. <el-tooltip
  498. content="请在登录时的url后拼接参数:tenantId={编号}"
  499. placement="top"
  500. >
  501. <i class="el-icon-question"></i>
  502. </el-tooltip>
  503. 编号:
  504. </span>
  505. <el-input
  506. v-model="loginForm.loginPageNumber"
  507. placeholder="请输入登录页面编号"
  508. disabled
  509. />
  510. </el-form-item>
  511. <!-- <el-col :span="8"> -->
  512. <el-form-item label="标题:" prop="loginPageTitle">
  513. <el-input
  514. v-model="loginForm.loginPageTitle"
  515. placeholder="请输入登录页面标题"
  516. />
  517. </el-form-item>
  518. <!-- </el-col> -->
  519. <!-- <el-col :span="8"> -->
  520. <el-form-item label="描述:" prop="loginPageDescription">
  521. <span slot="label">
  522. <el-tooltip
  523. content="推荐长度为8个汉字,可使用<br/>换行"
  524. placement="top"
  525. >
  526. <i class="el-icon-question"></i>
  527. </el-tooltip>
  528. 描述:
  529. </span>
  530. <el-input
  531. v-model="loginForm.loginPageDescription"
  532. type="textarea"
  533. placeholder="请输入内容"
  534. />
  535. </el-form-item>
  536. <!-- </el-col>
  537. <el-col :span="8"> -->
  538. <el-form-item label="窗口标题:" prop="windowTitle">
  539. <el-input
  540. v-model="loginForm.windowTitle"
  541. placeholder="请输入窗口标题"
  542. />
  543. </el-form-item>
  544. <!-- </el-col> -->
  545. <!-- <el-col :span="8"> -->
  546. <el-form-item prop="loginPageLogo">
  547. <span slot="label">
  548. <el-tooltip content="推荐图片大小为194*64px" placement="top">
  549. <i class="el-icon-question"></i>
  550. </el-tooltip>
  551. logo:
  552. </span>
  553. <image-upload :limit="1" v-model="loginForm.loginPageLogo" />
  554. </el-form-item>
  555. <!-- </el-col> -->
  556. <!-- <el-col :span="8"> -->
  557. <el-form-item prop="loginPageBackgroundImage">
  558. <span slot="label">
  559. <el-tooltip content="推荐图片大小为1400*900px" placement="top">
  560. <i class="el-icon-question"></i>
  561. </el-tooltip>
  562. 背景图:
  563. </span>
  564. <image-upload
  565. :limit="1"
  566. v-model="loginForm.loginPageBackgroundImage"
  567. />
  568. </el-form-item>
  569. <!-- </el-col> -->
  570. <!-- <el-col :span="8"> -->
  571. <!-- <el-form-item label="窗口logo:" prop="windowLogo">
  572. <image-upload
  573. :fileType="['png']"
  574. :limit="1"
  575. :uploadUrl="'/common/uploadAndConvert'"
  576. v-model="loginForm.windowLogo"
  577. />
  578. </el-form-item> -->
  579. <!-- </el-col> -->
  580. </el-form>
  581. <div slot="footer" class="dialog-footer">
  582. <el-button type="primary" @click="submitLoginForm">确 定</el-button>
  583. <el-button @click="cancelLoginForm">取 消</el-button>
  584. </div>
  585. </el-dialog>
  586. </div>
  587. </template>
  588. <script>
  589. import {
  590. listTenant,
  591. getTenant,
  592. delTenant,
  593. addTenant,
  594. updateTenant,
  595. bindDatasource,
  596. selectAllUser,
  597. createTenant,
  598. initTenantMenuData,
  599. activationOperation,
  600. getTenantChildrenInfo,
  601. getTenantAllList,
  602. tenantTree,
  603. } from "@/api/system/tenant";
  604. import { getDataSourceInfo, insertDataSource } from "@/api/system/data";
  605. import {
  606. listConfiguration,
  607. getConfiguration,
  608. delConfiguration,
  609. addConfiguration,
  610. updateConfiguration,
  611. } from "@/api/system/configuration";
  612. import { servicesLoading } from "@/utils/zkqy";
  613. import { getIsExistUser } from "@/api/system/user";
  614. import ExcelDownLoad from "@/components/ExcelDownLoad/index.vue";
  615. import { mapState } from "vuex";
  616. export default {
  617. name: "Tenant",
  618. dicts: [
  619. "datasource_type",
  620. "sqlserver_connection_information",
  621. "mysql_connection_information",
  622. "dm_connection_information",
  623. "orcale_connection_information",
  624. "system_login_url",
  625. ],
  626. components: {
  627. ExcelDownLoad,
  628. },
  629. data() {
  630. return {
  631. tenantAllList: [],
  632. // 登录页面数据
  633. isEdit: false,
  634. loginOpen: false,
  635. loginForm: {
  636. loginPageNumber: "",
  637. loginPageTitle: "",
  638. loginPageDescription: "",
  639. loginPageLogo: "",
  640. loginPageBackgroundImage: "",
  641. windowTitle: "",
  642. windowLogo: "",
  643. tenantId: "",
  644. },
  645. // 前端导出数据
  646. selection: [],
  647. headerList: {
  648. 租户名称: "tenantName",
  649. 租户编号: "tenantCode",
  650. 负责人: "owner",
  651. 联系方式: "contactInfo",
  652. 地址: "address",
  653. 是否删除: "isDel",
  654. },
  655. excelTitle: "tenant",
  656. // 弹窗的加载提示
  657. dialogLoading: false,
  658. // 遮罩层
  659. loading: true,
  660. // 选中数组
  661. ids: [],
  662. // 非单个禁用
  663. single: true,
  664. // 非多个禁用
  665. multiple: true,
  666. // 显示搜索条件
  667. showSearch: true,
  668. // 总条数
  669. total: 0,
  670. // 租户信息表格数据
  671. tenantList: [],
  672. // 弹出层标题
  673. title: "",
  674. // 是否显示弹出层
  675. open: false,
  676. // 所有用户信息
  677. allUser: [],
  678. // 查询参数
  679. queryParams: {
  680. pageNum: 1,
  681. pageSize: 10,
  682. tenantName: null,
  683. tenantCode: null,
  684. owner: null,
  685. contactInfo: null,
  686. address: null,
  687. },
  688. // 当前编辑租户的信息
  689. currentTenantInfo: {},
  690. // 表单参数
  691. form: {},
  692. // 表单校验
  693. rules: {
  694. tenantName: [
  695. { required: true, message: "租户名称不能为空", trigger: "blur" },
  696. ],
  697. tenantCode: [
  698. { required: true, message: "租户编号不能为空", trigger: "blur" },
  699. ],
  700. tenantParentId: [
  701. { required: true, message: "请选择上级租户", trigger: "blur" },
  702. ],
  703. },
  704. //数据源表单参数
  705. dataSourceType: true, //true:公网 false:内网
  706. dataSourceForm: {
  707. databaseType: "",
  708. databaseName: "",
  709. tenantAccount: "",
  710. databaseIp: "",
  711. username: "",
  712. password: "",
  713. portNumber: "",
  714. },
  715. dataSourceTitle: "",
  716. dataSourceOpen: false,
  717. fromTenantId: null,
  718. dataSourceFormRules: {
  719. databaseType: [
  720. { required: true, message: "数据源类型不能为空", trigger: "change" },
  721. ],
  722. databaseName: [
  723. { required: true, message: "数据库名不能为空", trigger: "blur" },
  724. { validator: this.databaseNameValidator, trigger: "blur" },
  725. ],
  726. tenantAccount: [
  727. {
  728. required: true,
  729. message: "租户管理员账号不能为空",
  730. trigger: "change",
  731. },
  732. { validator: this.tenantAccountValidator, trigger: "blur" },
  733. ],
  734. databaseIp: [
  735. { required: true, message: "数据库IP不能为空", trigger: "blur" },
  736. ],
  737. username: [
  738. { required: true, message: "用户名不能为空", trigger: "blur" },
  739. ],
  740. password: [
  741. { required: true, message: "密码不能为空", trigger: "blur" },
  742. ],
  743. portNumber: [
  744. { required: true, message: "端口号不能为空", trigger: "blur" },
  745. ],
  746. },
  747. //租户激活码弹窗表单
  748. tenantExpirationTimeFrom: {
  749. tenantId: null,
  750. tenantExpirationTime: "",
  751. },
  752. //租户激活码弹窗标题
  753. tenantExpirationTimeOpen: false,
  754. //租户激活码规则验证
  755. rulesTenantExpirationTime: {
  756. tenantExpirationTime: [
  757. { required: true, message: "请输入租户激活码", trigger: "blur" },
  758. ],
  759. },
  760. currentPage: "",
  761. // 已存在的数据库名称
  762. databaseNameList: [],
  763. tableData1: [
  764. {
  765. id: 1,
  766. date: "2016-05-02",
  767. name: "王小虎",
  768. address: "上海市普陀区金沙江路 1518 弄",
  769. },
  770. {
  771. id: 2,
  772. date: "2016-05-04",
  773. name: "王小虎",
  774. address: "上海市普陀区金沙江路 1517 弄",
  775. },
  776. {
  777. id: 3,
  778. date: "2016-05-01",
  779. name: "王小虎",
  780. address: "上海市普陀区金沙江路 1519 弄",
  781. hasChildren: true,
  782. },
  783. {
  784. id: 4,
  785. date: "2016-05-03",
  786. name: "王小虎",
  787. address: "上海市普陀区金沙江路 1516 弄",
  788. },
  789. ],
  790. };
  791. },
  792. computed: {
  793. palcemsg() {
  794. return this.dataSourceType ? "mysql" : "请选择数据源类型";
  795. },
  796. ...mapState({
  797. userInfo: (state) => state,
  798. }),
  799. },
  800. created() {
  801. this.getList();
  802. this.selectAllUser();
  803. },
  804. methods: {
  805. load(tree, treeNode, resolve) {
  806. console.log(tree, treeNode, resolve);
  807. // 根据当前租户id查询子租户
  808. getTenantChildrenInfo(tree.tenantId).then((res) => {
  809. if (res.data != null) {
  810. resolve(res.data);
  811. } else {
  812. resolve({});
  813. }
  814. });
  815. },
  816. // 查询所有平台所有租户
  817. getTenantAllList() {
  818. tenantTree().then((response) => {
  819. let tenantAllListOne = this.handleTree(
  820. response.data,
  821. "tenantId",
  822. "tenantParentId"
  823. );
  824. this.tenantAllList = [
  825. // { tenantId: 0, tenantName: "顶级租户" },
  826. ...tenantAllListOne,
  827. ];
  828. });
  829. },
  830. buildTree(data, parentId = null) {
  831. const children = data.filter((item) => item.tenantParentId === parentId);
  832. return children.map((child) => ({
  833. value: child.tenantId,
  834. label: child.tenantName,
  835. children: this.buildTree(data, child.tenantId), // 将 child.tenant_id 作为下一层的 parentId
  836. }));
  837. },
  838. transformTenantsToCascaderOptions(tenants) {
  839. console.log(tenants);
  840. const options = [];
  841. const map = {}; // 用于存储每个tenant的引用,以便后续添加children
  842. tenants.forEach((tenant) => {
  843. const { tenantId, tenantName, tenantParentId } = tenant;
  844. const option = {
  845. value: tenantId,
  846. label: tenantName,
  847. children: [], // 初始化children数组
  848. };
  849. if (tenantParentId === null) {
  850. // 如果没有父级,说明是顶级租户,直接添加到options中
  851. options.push(option);
  852. } else {
  853. // 如果有父级,则先查找父级租户在map中的引用,并添加到其children数组中
  854. if (!map[tenantParentId]) {
  855. // 如果父级租户还没被处理过,先创建一个空的引用
  856. map[tenantParentId] = { children: [] };
  857. }
  858. map[tenantParentId].children.push(option);
  859. }
  860. // 将当前租户添加到map中,方便后续查找
  861. map[tenantId] = option;
  862. });
  863. // 遍历map,将顶级租户的children填充完整
  864. Object.values(map).forEach((option) => {
  865. if (!options.includes(option)) {
  866. // 如果这个选项不是顶级租户,则将其添加到某个顶级租户的children中
  867. const parentOption = options.find((o) => o.children.includes(option));
  868. if (parentOption) {
  869. parentOption.children.push(option);
  870. }
  871. }
  872. });
  873. console.log(options);
  874. return options;
  875. },
  876. // 提交登录页配置数据
  877. submitLoginForm() {
  878. this.$refs.loginFormRef?.validate(async (valid) => {
  879. if (valid) {
  880. console.log(this.loginForm);
  881. let res = {},
  882. msg = "";
  883. if (this.isEdit) {
  884. res = await updateConfiguration(this.loginForm);
  885. msg = "修改";
  886. } else {
  887. res = await addConfiguration(this.loginForm);
  888. msg = "保存";
  889. }
  890. if (res.code == 200) {
  891. this.$message.success(`${msg}成功`);
  892. this.loginOpen = false;
  893. } else {
  894. this.$message.error(`${msg}失败,请检查网络`);
  895. }
  896. } else {
  897. console.log(`${msg}失败,请检查网络`);
  898. return false;
  899. }
  900. });
  901. },
  902. // 取消登录页配置
  903. cancelLoginForm() {
  904. this.loginOpen = false;
  905. },
  906. // 编辑租户登录页配置
  907. async openLoginConfig(row) {
  908. try {
  909. let res = await getConfiguration(row.tenantId);
  910. if (res.code == 200) {
  911. if (res.data) {
  912. this.loginForm = res.data;
  913. this.isEdit = true;
  914. } else {
  915. this.resetloginForm();
  916. this.isEdit = false;
  917. }
  918. // 目前一个租户只能有一个配置项故使用租户唯一编码
  919. this.loginForm.loginPageNumber = row.tenantCode;
  920. this.loginForm.tenantId = row.tenantId;
  921. this.loginOpen = true;
  922. } else {
  923. this.$message.error("网络异常,请稍后再试");
  924. }
  925. } catch (error) {}
  926. },
  927. // 获取所用用户名,作校验用
  928. async selectAllUser() {
  929. let res = await selectAllUser();
  930. if (res.code == 200) {
  931. this.allUser = res.data;
  932. } else {
  933. console.log(res.msg);
  934. }
  935. },
  936. // 重置login配置表单数据
  937. resetloginForm() {
  938. this.loginForm = {
  939. loginPageNumber: "",
  940. loginPageTitle: "",
  941. loginPageDescription: "",
  942. loginPageLogo: "",
  943. loginPageBackgroundImage: "",
  944. windowTitle: "",
  945. windowLogo: "",
  946. tenantId: "",
  947. };
  948. },
  949. // 租户名自定义校验规则
  950. async tenantAccountValidator(rule, value, callback) {
  951. // let isRepeat = this.allUser.filter((item) => item.userName == value);
  952. // if (isRepeat.length !== 0) {
  953. // callback(new Error("租户账号重复"));
  954. // } else {
  955. // callback();
  956. // }
  957. if (value) {
  958. await getIsExistUser({ userName: value }).then((res) => {
  959. if (res.code == 200) {
  960. if (res.data) {
  961. callback();
  962. } else {
  963. callback(new Error("租户管理员账号已存在"));
  964. }
  965. } else {
  966. callback(new Error("租户管理员账号校验失败,请重新输入"));
  967. }
  968. });
  969. }
  970. callback();
  971. },
  972. // 数据库名自定义校验规则--请求后端校验
  973. // async databaseNameValidator(rule, value, callback) {
  974. // if (value) {
  975. // await getDataSourceInfo({ databaseName: value }).then((res) => {
  976. // if (res.code == 200) {
  977. // if (res.data) {
  978. // callback();
  979. // } else {
  980. // callback(new Error("数据库名已存在"));
  981. // }
  982. // } else {
  983. // callback(new Error("数据库名校验失败,请重新输入"));
  984. // }
  985. // });
  986. // }
  987. // },
  988. // 数据库名称校验规则
  989. databaseNameValidator(rule, value, callback) {
  990. // 正则校验
  991. let regex = /^[a-z][a-z0-9]*$/;
  992. if (regex.test(value)) {
  993. // callback(); // 输入内容符合规则
  994. } else {
  995. callback(new Error("只能包含小写字母和数字,且以小写字母开头"));
  996. }
  997. // 重名校验
  998. let isRepeat = this.databaseNameList.filter((item) => item == value);
  999. if (isRepeat.length !== 0) {
  1000. callback(new Error("数据库名重复"));
  1001. } else {
  1002. callback();
  1003. }
  1004. },
  1005. // 数据源类型改变回调
  1006. dataSourceTypeChange(type) {
  1007. this.$nextTick(() => {
  1008. this.$refs.dataSourceForm.resetFields();
  1009. this.dataSourceForm.databaseType = "mysql";
  1010. this.selecthandle("mysql");
  1011. });
  1012. },
  1013. handleOpe() {},
  1014. /** 查询租户信息列表 */
  1015. getList() {
  1016. this.loading = true;
  1017. this.currentPage = this.queryParams.pageNum;
  1018. this.queryParams.tenantParentId = this.userInfo.user.tenant.tenantId;
  1019. getTenantAllList(this.queryParams).then((response) => {
  1020. this.tenantList = response.rows;
  1021. this.tenantList.forEach((item) => {
  1022. item["hasChildren"] = true;
  1023. });
  1024. this.total = response.total;
  1025. this.loading = false;
  1026. });
  1027. },
  1028. // 取消按钮
  1029. cancel() {
  1030. this.open = false;
  1031. this.reset();
  1032. },
  1033. // 绑定数据源取消按钮
  1034. cancel1() {
  1035. this.dataSourceOpen = false;
  1036. this.reset1();
  1037. },
  1038. // 表单重置
  1039. reset() {
  1040. this.form = {
  1041. tenantParentId: null,
  1042. tenantId: null,
  1043. tenantName: null,
  1044. tenantCode: null,
  1045. owner: null,
  1046. contactInfo: null,
  1047. address: null,
  1048. createBy: null,
  1049. createTime: null,
  1050. };
  1051. this.resetForm("form");
  1052. },
  1053. // 表单重置
  1054. reset1() {
  1055. this.dataSourceType = true;
  1056. this.dataSourceForm = {
  1057. id: null,
  1058. databaseName: null,
  1059. databaseIp: null,
  1060. tenantAccount: "",
  1061. username: null,
  1062. password: null,
  1063. portNumber: null,
  1064. databaseType: "mysql",
  1065. };
  1066. // this.resetForm("dataSourceForm");
  1067. },
  1068. /** 搜索按钮操作 */
  1069. handleQuery() {
  1070. this.queryParams.pageNum = 1;
  1071. this.getList();
  1072. },
  1073. /** 重置按钮操作 */
  1074. resetQuery() {
  1075. this.resetForm("queryForm");
  1076. this.handleQuery();
  1077. },
  1078. // 多选框选中数据
  1079. handleSelectionChange(selection) {
  1080. this.selection = selection;
  1081. this.ids = selection.map((item) => item.tenantId);
  1082. this.single = selection.length !== 1;
  1083. this.multiple = !selection.length;
  1084. },
  1085. /** 新增按钮操作 */
  1086. handleAdd() {
  1087. this.getTenantAllList();
  1088. // this.reset();
  1089. this.open = true;
  1090. this.title = "添加租户信息";
  1091. },
  1092. /** 修改按钮操作 */
  1093. handleUpdate(row) {
  1094. this.reset();
  1095. const tenantId = row.tenantId || this.ids;
  1096. getTenant(tenantId).then((response) => {
  1097. this.form = response.data;
  1098. this.open = true;
  1099. this.title = "修改租户信息";
  1100. });
  1101. },
  1102. /** 绑定数据源按钮操作 */
  1103. bindDatasource(row) {
  1104. this.currentTenantInfo = row;
  1105. this.reset1();
  1106. this.dialogLoading = false;
  1107. this.dataSourceOpen = true;
  1108. this.dataSourceTitle = row.tenantName + "配置数据库";
  1109. this.fromTenantId = row.tenantId;
  1110. this.dataSourceTypeChange();
  1111. // const tenantId = row.tenantId || this.ids;
  1112. // getTenant(tenantId).then((response) => {
  1113. // this.form = response.data;
  1114. // this.open = true;
  1115. // this.title = "修改租户信息";
  1116. // });
  1117. },
  1118. /** 提交按钮 */
  1119. submitForm() {
  1120. if (this.form.tenantParentId.length >= 0) {
  1121. // 处理当前租户的上级租户id
  1122. this.form.tenantParentId =
  1123. this.form.tenantParentId[this.form.tenantParentId.length - 1] !=
  1124. undefined
  1125. ? this.form.tenantParentId[this.form.tenantParentId.length - 1]
  1126. : "";
  1127. }
  1128. this.form.tenantClientLoginUrl = this.dict.type.system_login_url
  1129. .find((item) => item.label == "client_login_url")
  1130. ?.value.replace("#{val}", this.form.tenantCode);
  1131. this.form.tenantToolLoginUrl = this.dict.type.system_login_url
  1132. .find((item) => item.label == "crm_login_url")
  1133. ?.value.replace("#{val}", this.form.tenantCode);
  1134. this.$refs["form"].validate((valid) => {
  1135. if (valid) {
  1136. if (this.form.tenantId != null) {
  1137. updateTenant(this.form).then((response) => {
  1138. this.$modal.msgSuccess("修改成功");
  1139. this.open = false;
  1140. this.getList();
  1141. });
  1142. } else {
  1143. addTenant(this.form).then((response) => {
  1144. this.$modal.msgSuccess("新增成功");
  1145. this.open = false;
  1146. this.getList();
  1147. });
  1148. }
  1149. }
  1150. this.reset();
  1151. });
  1152. },
  1153. /** 提交按钮 */
  1154. submitForm1() {
  1155. if (this.dialogLoading) return;
  1156. this.dialogLoading = true;
  1157. this.$refs["dataSourceForm"].validate((valid) => {
  1158. if (valid) {
  1159. // const loading = servicesLoading(
  1160. // ".loadingClass",
  1161. // "正在绑定数据源",
  1162. // true
  1163. // );
  1164. if (this.dataSourceForm.id != null) {
  1165. // bindDatasource(this.dataSourceForm).then((response) => {
  1166. // this.$modal.msgSuccess("修改成功");
  1167. // this.dataSourceOpen = false;
  1168. // this.getList();
  1169. // });
  1170. this.dialogLoading = false;
  1171. } else {
  1172. let query = {
  1173. tenantId: this.fromTenantId,
  1174. dataSource: this.dataSourceForm,
  1175. };
  1176. bindDatasource(query)
  1177. .then((response) => {
  1178. if (response.code == 200) {
  1179. let data = {
  1180. userName: this.dataSourceForm.tenantAccount,
  1181. nickName: this.currentTenantInfo.tenantName,
  1182. userType: "01",
  1183. tenantId: this.currentTenantInfo.tenantId,
  1184. password: "123456",
  1185. };
  1186. createTenant(data)
  1187. .then(async (res) => {
  1188. if (res.code == 200) {
  1189. let resp = await initTenantMenuData(
  1190. this.currentTenantInfo.tenantId
  1191. );
  1192. if ((resp.code = 200)) {
  1193. this.$modal.msgSuccess("新增成功");
  1194. this.dataSourceOpen = false;
  1195. this.getList();
  1196. }
  1197. }
  1198. })
  1199. .finally(() => {
  1200. this.dialogLoading = false;
  1201. });
  1202. }
  1203. })
  1204. .finally(() => {
  1205. this.dialogLoading = false;
  1206. });
  1207. }
  1208. }
  1209. });
  1210. },
  1211. /** 删除按钮操作 */
  1212. handleDelete(row) {
  1213. const tenantIds = row.tenantId || this.ids;
  1214. this.$modal
  1215. .confirm('是否确认删除租户信息编号为"' + tenantIds + '"的数据项?')
  1216. .then(function () {
  1217. return delTenant(tenantIds);
  1218. })
  1219. .then(() => {
  1220. this.getList();
  1221. this.$modal.msgSuccess("删除成功");
  1222. })
  1223. .catch(() => {});
  1224. },
  1225. /** 导出按钮操作 */
  1226. handleExport() {
  1227. this.download(
  1228. "system/tenant/export",
  1229. {
  1230. ...this.queryParams,
  1231. },
  1232. `tenant_${new Date().getTime()}.xlsx`
  1233. );
  1234. },
  1235. /**
  1236. * 选择数据源校验名称
  1237. */
  1238. selecthandle(row) {
  1239. let sql = {
  1240. sqlserver: "sqlserver_connection_information",
  1241. mysql: "mysql_connection_information",
  1242. dm: "dm_connection_information",
  1243. oracle: "oracle_connection_information",
  1244. };
  1245. let qar = {};
  1246. this.dict.type[sql[row]].forEach((item) => {
  1247. qar[item.label] = item.value;
  1248. });
  1249. if (this.dataSourceType) {
  1250. let { databaseIp, password, portNumber, username } = qar;
  1251. Object.assign(this.dataSourceForm, {
  1252. databaseIp,
  1253. password,
  1254. portNumber,
  1255. username,
  1256. });
  1257. }
  1258. getDataSourceInfo(qar).then((res) => {
  1259. // console.log(res);
  1260. this.databaseNameList = res.data;
  1261. });
  1262. },
  1263. handleTest() {
  1264. let formdata = {
  1265. databaseType: "mysql",
  1266. databaseName: "test1111",
  1267. databaseIp: "127.0.0.1",
  1268. username: "testname",
  1269. password: "123123",
  1270. portNumber: "3306",
  1271. };
  1272. insertDataSource(formdata).then((res) => {
  1273. console.log(res);
  1274. });
  1275. },
  1276. //重置租户激活码表单
  1277. restTenantExpirationTime() {
  1278. this.tenantExpirationTimeFrom = {
  1279. tenantId: null,
  1280. tenantExpirationTime: "",
  1281. };
  1282. this.resetForm("tenantExpirationTimeFrom");
  1283. },
  1284. /**打开激活码弹窗*/
  1285. openTenantExpirationTime(row) {
  1286. // this.reset();
  1287. const tenantId = row.tenantId || this.ids;
  1288. this.tenantExpirationTimeFrom.tenantId = row.tenantId;
  1289. this.tenantExpirationTimeOpen = true;
  1290. // this.title="激活租户";
  1291. },
  1292. /**激活租户操作*/
  1293. activationOperationMethod(form) {
  1294. this.$refs[form].validate(async (valid) => {
  1295. if (valid) {
  1296. let response = await activationOperation(
  1297. this.tenantExpirationTimeFrom
  1298. );
  1299. if (response.code == 200) {
  1300. this.$message.success("激活成功");
  1301. //重新刷新列表
  1302. this.getList();
  1303. } else {
  1304. this.$message.error("激活失败");
  1305. }
  1306. this.tenantExpirationTimeOpen = false;
  1307. this.tenantExpirationTimeFrom = {
  1308. tenantId: null,
  1309. tenantExpirationTime: null,
  1310. };
  1311. }
  1312. });
  1313. },
  1314. // 激活租户对话框取消按钮
  1315. tanentCancel() {
  1316. this.tenantExpirationTimeOpen = false;
  1317. this.tenantExpirationTimeFrom = {
  1318. tenantId: null,
  1319. tenantExpirationTime: null,
  1320. };
  1321. },
  1322. },
  1323. };
  1324. </script>