index.vue 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998
  1. <template>
  2. <div class="agent-page">
  3. <div class="agent-panel">
  4. <el-form
  5. ref="queryForm"
  6. :model="query"
  7. class="agent-search"
  8. inline
  9. size="small"
  10. >
  11. <el-form-item label="代理账号" prop="agent_account">
  12. <el-input
  13. v-model="query.agent_account"
  14. placeholder="代理账号"
  15. clearable
  16. />
  17. </el-form-item>
  18. <el-form-item label="真实姓名" prop="real_name">
  19. <el-input
  20. v-model="query.real_name"
  21. placeholder="真实姓名"
  22. clearable
  23. />
  24. </el-form-item>
  25. <el-form-item label="账号状态" prop="status">
  26. <el-select v-model="query.status" placeholder="账号状态" clearable>
  27. <el-option label="启用" :value="1" />
  28. <el-option label="禁用" :value="0" />
  29. </el-select>
  30. </el-form-item>
  31. <el-form-item label="注册时间" prop="date_range">
  32. <el-date-picker
  33. v-model="query.date_range"
  34. type="daterange"
  35. range-separator="-"
  36. start-placeholder="开始日期"
  37. end-placeholder="结束日期"
  38. value-format="yyyy-MM-dd"
  39. :picker-options="disableFutureDate"
  40. />
  41. </el-form-item>
  42. <el-form-item class="search-actions">
  43. <el-button @click="handleSearch">查询</el-button>
  44. <el-button type="primary" icon="el-icon-plus" @click="handleAdd">
  45. 新增
  46. </el-button>
  47. </el-form-item>
  48. </el-form>
  49. <el-table
  50. v-loading="loading"
  51. :data="tableData"
  52. border
  53. height="calc(100vh - 255px)"
  54. class="agent-table"
  55. :row-class-name="tableRowClassName"
  56. >
  57. <el-table-column prop="id" label="ID" width="58" align="center" />
  58. <el-table-column prop="agent_account" label="代理账号" min-width="120" align="center" />
  59. <el-table-column prop="invite_code" label="邀请码" min-width="120" align="center" />
  60. <el-table-column prop="real_name" label="真实姓名" min-width="120" align="center" />
  61. <el-table-column prop="parent_agent" label="上级代理" min-width="100" align="center" />
  62. <el-table-column prop="balance" label="账户余额" min-width="100" align="center">
  63. <template slot-scope="{ row }">
  64. {{ formatMoney(row.balance) }}
  65. </template>
  66. </el-table-column>
  67. <el-table-column prop="deposit_fee_rate" label="存款手续费比例" min-width="130" align="center">
  68. <template slot-scope="{ row }">
  69. {{ formatRate(row.deposit_fee_rate) }}
  70. </template>
  71. </el-table-column>
  72. <el-table-column prop="withdraw_fee_rate" label="取款手续费比例" min-width="130" align="center">
  73. <template slot-scope="{ row }">
  74. {{ formatRate(row.withdraw_fee_rate) }}
  75. </template>
  76. </el-table-column>
  77. <el-table-column prop="pc_agent_link" label="电脑代理链接" min-width="130" align="center">
  78. <template slot-scope="{ row }">
  79. <div class="link-cell">{{ row.pc_agent_link || '--' }}</div>
  80. </template>
  81. </el-table-column>
  82. <el-table-column prop="h5_agent_link" label="手机代理链接" min-width="130" align="center">
  83. <template slot-scope="{ row }">
  84. <div class="link-cell">{{ row.h5_agent_link || '--' }}</div>
  85. </template>
  86. </el-table-column>
  87. <el-table-column prop="status" label="账号状态" width="100" align="center">
  88. <template slot-scope="{ row }">
  89. <el-switch
  90. v-model="row.status"
  91. :active-value="1"
  92. :inactive-value="0"
  93. active-color="#20c76a"
  94. inactive-color="#dcdfe6"
  95. @change="handleStatusChange(row)"
  96. />
  97. </template>
  98. </el-table-column>
  99. <el-table-column prop="login_status" label="登录状态" width="90" align="center">
  100. <template slot-scope="{ row }">
  101. <el-tag
  102. size="mini"
  103. :type="row.login_status === 1 ? 'success' : 'info'"
  104. effect="plain"
  105. >
  106. {{ row.login_status === 1 ? '在线' : '离线' }}
  107. </el-tag>
  108. </template>
  109. </el-table-column>
  110. <el-table-column prop="login_time" label="登录时间" min-width="150" align="center">
  111. <template slot-scope="{ row }">
  112. {{ row.login_time || '--' }}
  113. </template>
  114. </el-table-column>
  115. <el-table-column label="操作" width="200" fixed="right" align="center">
  116. <template slot-scope="{ row }">
  117. <div class="row-actions">
  118. <el-button type="text" size="mini" @click="handleEdit(row)">修改</el-button>
  119. <el-button type="text" size="mini" @click="handleBindDomain(row)">绑定域名</el-button>
  120. <el-button type="text" size="mini" @click="handleAdjustBalance(row)">加/扣款</el-button>
  121. <el-button type="text" size="mini" @click="handleQuota(row)">额度管理</el-button>
  122. </div>
  123. </template>
  124. </el-table-column>
  125. </el-table>
  126. <el-pagination
  127. background
  128. class="agent-pagination"
  129. layout="total, sizes, prev, pager, next, jumper"
  130. :current-page="page"
  131. :page-size="limit"
  132. :page-sizes="[10, 20, 50, 100]"
  133. :total="total"
  134. @size-change="handleSizeChange"
  135. @current-change="handleCurrentChange"
  136. />
  137. </div>
  138. <el-dialog
  139. :title="agentDialogTitle"
  140. :visible.sync="agentDialogVisible"
  141. width="620px"
  142. @close="resetAgentForm"
  143. >
  144. <el-form
  145. ref="agentForm"
  146. :model="agentForm"
  147. :rules="agentRules"
  148. label-width="120px"
  149. size="small"
  150. >
  151. <el-form-item label="代理账号" prop="agent_account">
  152. <el-input v-model="agentForm.agent_account" placeholder="请输入代理账号" />
  153. </el-form-item>
  154. <el-form-item v-if="agentDialogType === 'add'" label="登录密码" prop="password">
  155. <el-input v-model="agentForm.password" placeholder="请输入登录密码" show-password />
  156. </el-form-item>
  157. <el-form-item label="真实姓名" prop="real_name">
  158. <el-input v-model="agentForm.real_name" placeholder="请输入真实姓名" />
  159. </el-form-item>
  160. <el-form-item label="上级代理" prop="parent_agent">
  161. <el-input v-model="agentForm.parent_agent" placeholder="请输入上级代理" />
  162. </el-form-item>
  163. <el-form-item label="账户余额" prop="balance">
  164. <el-input-number
  165. v-model="agentForm.balance"
  166. :min="0"
  167. :precision="2"
  168. :step="100"
  169. controls-position="right"
  170. class="full-input"
  171. />
  172. </el-form-item>
  173. <el-form-item label="存款手续费比例" prop="deposit_fee_rate">
  174. <el-input-number
  175. v-model="agentForm.deposit_fee_rate"
  176. :min="0"
  177. :max="100"
  178. :precision="2"
  179. :step="0.1"
  180. controls-position="right"
  181. class="full-input"
  182. />
  183. </el-form-item>
  184. <el-form-item label="取款手续费比例" prop="withdraw_fee_rate">
  185. <el-input-number
  186. v-model="agentForm.withdraw_fee_rate"
  187. :min="0"
  188. :max="100"
  189. :precision="2"
  190. :step="0.1"
  191. controls-position="right"
  192. class="full-input"
  193. />
  194. </el-form-item>
  195. <el-form-item label="账号状态" prop="status">
  196. <el-radio-group v-model="agentForm.status">
  197. <el-radio :label="1">启用</el-radio>
  198. <el-radio :label="0">禁用</el-radio>
  199. </el-radio-group>
  200. </el-form-item>
  201. </el-form>
  202. <div slot="footer">
  203. <el-button size="small" @click="agentDialogVisible = false">取消</el-button>
  204. <el-button type="primary" size="small" @click="submitAgent">确定</el-button>
  205. </div>
  206. </el-dialog>
  207. <el-dialog
  208. title="绑定域名"
  209. :visible.sync="domainDialogVisible"
  210. width="560px"
  211. >
  212. <el-form :model="domainForm" label-width="120px" size="small">
  213. <el-form-item label="电脑代理链接">
  214. <el-input v-model="domainForm.pc_agent_link" placeholder="请输入电脑代理链接" />
  215. </el-form-item>
  216. <el-form-item label="手机代理链接">
  217. <el-input v-model="domainForm.h5_agent_link" placeholder="请输入手机代理链接" />
  218. </el-form-item>
  219. </el-form>
  220. <div slot="footer">
  221. <el-button size="small" @click="domainDialogVisible = false">取消</el-button>
  222. <el-button type="primary" size="small" @click="submitDomain">确定</el-button>
  223. </div>
  224. </el-dialog>
  225. <el-dialog
  226. title="加/扣款"
  227. :visible.sync="balanceDialogVisible"
  228. width="520px"
  229. >
  230. <el-form ref="balanceForm" :model="balanceForm" :rules="balanceRules" label-width="100px" size="small">
  231. <el-form-item label="类型" prop="type">
  232. <el-radio-group v-model="balanceForm.type">
  233. <el-radio label="plus">加款</el-radio>
  234. <el-radio label="minus">扣款</el-radio>
  235. </el-radio-group>
  236. </el-form-item>
  237. <el-form-item label="金额" prop="amount">
  238. <el-input-number
  239. v-model="balanceForm.amount"
  240. :min="0.01"
  241. :precision="2"
  242. :step="100"
  243. controls-position="right"
  244. class="full-input"
  245. />
  246. </el-form-item>
  247. <el-form-item label="备注" prop="remark">
  248. <el-input v-model="balanceForm.remark" type="textarea" :rows="3" placeholder="请输入备注" />
  249. </el-form-item>
  250. </el-form>
  251. <div slot="footer">
  252. <el-button size="small" @click="balanceDialogVisible = false">取消</el-button>
  253. <el-button type="primary" size="small" @click="submitBalance">确定</el-button>
  254. </div>
  255. </el-dialog>
  256. <el-dialog
  257. title="额度管理"
  258. :visible.sync="quotaDialogVisible"
  259. width="1000px"
  260. custom-class="quota-dialog"
  261. >
  262. <div class="quota-content">
  263. <el-form
  264. ref="quotaTransferForm"
  265. :model="quotaTransferForm"
  266. :rules="quotaTransferRules"
  267. class="quota-transfer-form"
  268. inline
  269. label-width="86px"
  270. size="small"
  271. >
  272. <div class="quota-top-row">
  273. <el-form-item label="用户余额">
  274. <el-input v-model="quotaTransferForm.user_balance" readonly />
  275. </el-form-item>
  276. <el-button type="danger" size="small" @click="refreshUserBalance">
  277. 刷新余额
  278. </el-button>
  279. <el-button type="danger" size="small" @click="refreshAllPlatformBalance">
  280. 一键刷新
  281. </el-button>
  282. <el-button type="danger" size="small" @click="transferAllOut">
  283. 一键转出
  284. </el-button>
  285. </div>
  286. <div class="quota-transfer-row">
  287. <el-form-item label="转账类型" prop="transfer_type" required>
  288. <el-select v-model="quotaTransferForm.transfer_type" placeholder="转账类型">
  289. <el-option label="转入平台" value="in" />
  290. <el-option label="转出平台" value="out" />
  291. </el-select>
  292. </el-form-item>
  293. <el-form-item label="转账平台" prop="platform" required>
  294. <el-select v-model="quotaTransferForm.platform" placeholder="转账平台">
  295. <el-option
  296. v-for="item in platformBalances"
  297. :key="item.key"
  298. :label="item.name"
  299. :value="item.key"
  300. />
  301. </el-select>
  302. </el-form-item>
  303. <el-form-item label="转账金额" prop="amount" required>
  304. <el-input
  305. v-model="quotaTransferForm.amount"
  306. placeholder="请输入转账金额"
  307. />
  308. </el-form-item>
  309. <el-button type="success" size="small" @click="submitQuotaTransfer">
  310. 额度转换
  311. </el-button>
  312. </div>
  313. </el-form>
  314. <div class="platform-grid">
  315. <div
  316. v-for="item in platformBalances"
  317. :key="item.key"
  318. class="platform-card"
  319. >
  320. <div class="platform-refresh">
  321. <el-input
  322. :value="formatPlatformBalance(item)"
  323. readonly
  324. placeholder="请刷新"
  325. />
  326. <el-button icon="el-icon-refresh" @click="refreshPlatformBalance(item)" />
  327. </div>
  328. <div class="platform-name">{{ item.name }}</div>
  329. </div>
  330. </div>
  331. </div>
  332. </el-dialog>
  333. </div>
  334. </template>
  335. <script>
  336. import { disableFutureDate } from '@/utils/index'
  337. export default {
  338. name: 'AgentList',
  339. data() {
  340. return {
  341. loading: false,
  342. query: {
  343. agent_account: '',
  344. real_name: '',
  345. status: '',
  346. date_range: []
  347. },
  348. page: 1,
  349. limit: 10,
  350. total: 0,
  351. tableData: [],
  352. agentDialogVisible: false,
  353. agentDialogType: 'add',
  354. agentForm: this.getDefaultAgentForm(),
  355. agentRules: {
  356. agent_account: [
  357. { required: true, message: '请输入代理账号', trigger: 'blur' }
  358. ],
  359. password: [
  360. { required: true, message: '请输入登录密码', trigger: 'blur' }
  361. ]
  362. },
  363. domainDialogVisible: false,
  364. domainForm: {
  365. id: '',
  366. pc_agent_link: '',
  367. h5_agent_link: ''
  368. },
  369. balanceDialogVisible: false,
  370. balanceForm: {
  371. id: '',
  372. type: 'plus',
  373. amount: 0,
  374. remark: ''
  375. },
  376. balanceRules: {
  377. amount: [
  378. { required: true, message: '请输入金额', trigger: 'blur' }
  379. ],
  380. remark: [
  381. { required: true, message: '请输入备注', trigger: 'blur' }
  382. ]
  383. },
  384. quotaDialogVisible: false,
  385. activeQuotaAgent: null,
  386. quotaTransferForm: {
  387. id: '',
  388. user_balance: 0,
  389. transfer_type: '',
  390. platform: '',
  391. amount: ''
  392. },
  393. quotaTransferRules: {
  394. transfer_type: [
  395. { required: true, message: '请选择转账类型', trigger: 'change' }
  396. ],
  397. platform: [
  398. { required: true, message: '请选择转账平台', trigger: 'change' }
  399. ],
  400. amount: [
  401. { required: true, message: '请输入转账金额', trigger: 'blur' }
  402. ]
  403. },
  404. platformBalances: this.getDefaultPlatformBalances()
  405. }
  406. },
  407. computed: {
  408. agentDialogTitle() {
  409. return this.agentDialogType === 'add' ? '新增代理' : '修改代理'
  410. },
  411. // 禁止选择未来日期
  412. disableFutureDate() {
  413. return disableFutureDate
  414. }
  415. },
  416. created() {
  417. this.getList()
  418. },
  419. methods: {
  420. getDefaultPlatformBalances() {
  421. return [
  422. { key: 'fg', name: 'FG钱包', balance: null },
  423. { key: 'esb', name: 'ESB电竞', balance: null },
  424. { key: 'db5', name: 'DB5电竞', balance: null },
  425. { key: 'bg', name: 'BG钱包', balance: null },
  426. { key: 'ag', name: 'AG钱包', balance: null },
  427. { key: 'ss', name: 'SS体育', balance: null },
  428. { key: 'mw', name: 'MW钱包', balance: null },
  429. { key: 'newbb', name: 'NEWBB体育', balance: null },
  430. { key: 'cq9', name: 'CQ9钱包', balance: null },
  431. { key: 'jdb', name: 'JDB钱包', balance: null },
  432. { key: 'saba', name: 'SABA体育', balance: null },
  433. { key: 'ky', name: 'KY钱包', balance: null },
  434. { key: 'pt', name: 'PT捕鱼', balance: null },
  435. { key: 'tf', name: 'TF电竞', balance: null },
  436. { key: 'mt', name: 'MT钱包', balance: null },
  437. { key: 'cmd', name: 'CMD体育', balance: null },
  438. { key: 'wl', name: 'WL钱包', balance: null },
  439. { key: 'mg', name: 'MG钱包', balance: null },
  440. { key: 'joker', name: 'JOKER钱包', balance: null },
  441. { key: 'db7', name: 'DB7棋牌', balance: null },
  442. { key: 'panda', name: 'PANDA体育', balance: null },
  443. { key: 'db3', name: 'DB3彩票', balance: null },
  444. { key: 'db2', name: 'DB2电子', balance: null },
  445. { key: 'db1', name: 'DB1真人', balance: null },
  446. { key: 'pg', name: 'PG电子', balance: null },
  447. { key: 'og', name: 'OG真人', balance: null },
  448. { key: 'db6', name: 'DB6捕鱼', balance: null },
  449. { key: 'sexy', name: 'SEXY真人', balance: null },
  450. { key: 'leg', name: 'LEG钱包', balance: null },
  451. { key: 'sgwin', name: 'SGWIN彩票', balance: null }
  452. ]
  453. },
  454. getDefaultAgentForm() {
  455. return {
  456. id: '',
  457. agent_account: '',
  458. password: '',
  459. invite_code: '',
  460. real_name: '',
  461. parent_agent: '',
  462. balance: 0,
  463. deposit_fee_rate: 0,
  464. withdraw_fee_rate: 0,
  465. status: 1
  466. }
  467. },
  468. getMockRows() {
  469. return [
  470. {
  471. id: 495,
  472. agent_account: 'qwe775825',
  473. invite_code: '',
  474. real_name: '',
  475. parent_agent: 'agent',
  476. balance: 1000000,
  477. deposit_fee_rate: 0,
  478. withdraw_fee_rate: 0,
  479. pc_agent_link: 'https://pc-yx.ng-demo.xyz/?directAgent=495#/user/register',
  480. h5_agent_link: 'https://h5-yx.ng-demo.xyz/?directAgent=495#/pages/login/login?type=reg',
  481. status: 1,
  482. login_status: 0,
  483. login_time: ''
  484. },
  485. {
  486. id: 494,
  487. agent_account: 'gifvip999',
  488. invite_code: '',
  489. real_name: '',
  490. parent_agent: 'agent',
  491. balance: 0,
  492. deposit_fee_rate: 0,
  493. withdraw_fee_rate: 0,
  494. pc_agent_link: 'https://pc-yx.ng-demo.xyz/?directAgent=494#/user/register',
  495. h5_agent_link: 'https://h5-yx.ng-demo.xyz/?directAgent=494#/pages/login/login?type=reg',
  496. status: 1,
  497. login_status: 0,
  498. login_time: ''
  499. },
  500. {
  501. id: 493,
  502. agent_account: 'aasd5396625',
  503. invite_code: '',
  504. real_name: '',
  505. parent_agent: 'agent',
  506. balance: 0,
  507. deposit_fee_rate: 0,
  508. withdraw_fee_rate: 0,
  509. pc_agent_link: 'https://pc-yx.ng-demo.xyz/?directAgent=493#/user/register',
  510. h5_agent_link: 'https://h5-yx.ng-demo.xyz/?directAgent=493#/pages/login/login?type=reg',
  511. status: 1,
  512. login_status: 0,
  513. login_time: ''
  514. },
  515. {
  516. id: 492,
  517. agent_account: 'aasd775825',
  518. invite_code: '',
  519. real_name: '',
  520. parent_agent: 'agent',
  521. balance: 0,
  522. deposit_fee_rate: 0,
  523. withdraw_fee_rate: 0,
  524. pc_agent_link: 'https://web.google.com/?directAgent=492#/user/register',
  525. h5_agent_link: 'https://wap.google.com/?directAgent=492#/pages/login/login?type=reg',
  526. status: 1,
  527. login_status: 0,
  528. login_time: ''
  529. },
  530. {
  531. id: 479,
  532. agent_account: 'sub8007',
  533. invite_code: '',
  534. real_name: 's',
  535. parent_agent: 'agpwn27963',
  536. balance: 0,
  537. deposit_fee_rate: 0,
  538. withdraw_fee_rate: 0,
  539. pc_agent_link: 'https://pc-yx.ng-demo.xyz/?directAgent=479#/user/register',
  540. h5_agent_link: 'https://h5-yx.ng-demo.xyz/?directAgent=479#/pages/login/login?type=reg',
  541. status: 1,
  542. login_status: 0,
  543. login_time: ''
  544. }
  545. ]
  546. },
  547. getList() {
  548. this.loading = true
  549. const rows = this.getMockRows().filter(item => {
  550. const accountMatched = !this.query.agent_account || item.agent_account.indexOf(this.query.agent_account) > -1
  551. const realNameMatched = !this.query.real_name || item.real_name.indexOf(this.query.real_name) > -1
  552. const statusMatched = this.query.status === '' || item.status === this.query.status
  553. return accountMatched && realNameMatched && statusMatched
  554. })
  555. this.total = rows.length
  556. this.tableData = rows.slice((this.page - 1) * this.limit, this.page * this.limit)
  557. this.loading = false
  558. },
  559. handleSearch() {
  560. this.page = 1
  561. this.getList()
  562. },
  563. handleSizeChange(val) {
  564. this.limit = val
  565. this.page = 1
  566. this.getList()
  567. },
  568. handleCurrentChange(val) {
  569. this.page = val
  570. this.getList()
  571. },
  572. tableRowClassName({ rowIndex }) {
  573. return rowIndex % 2 === 1 ? 'agent-row-tint' : ''
  574. },
  575. formatMoney(value) {
  576. const numberValue = Number(value)
  577. if (Number.isNaN(numberValue)) return value || 0
  578. return Number.isInteger(numberValue) ? numberValue : numberValue.toFixed(2)
  579. },
  580. formatRate(value) {
  581. const numberValue = Number(value)
  582. if (Number.isNaN(numberValue)) return value || 0
  583. return numberValue
  584. },
  585. handleAdd() {
  586. this.agentDialogType = 'add'
  587. this.agentForm = this.getDefaultAgentForm()
  588. this.agentDialogVisible = true
  589. this.$nextTick(() => {
  590. this.$refs.agentForm && this.$refs.agentForm.clearValidate()
  591. })
  592. },
  593. handleEdit(row) {
  594. this.agentDialogType = 'edit'
  595. this.agentForm = Object.assign(this.getDefaultAgentForm(), row)
  596. this.agentDialogVisible = true
  597. this.$nextTick(() => {
  598. this.$refs.agentForm && this.$refs.agentForm.clearValidate()
  599. })
  600. },
  601. submitAgent() {
  602. this.$refs.agentForm.validate(valid => {
  603. if (!valid) return
  604. if (this.agentDialogType === 'add') {
  605. const row = Object.assign({}, this.agentForm, {
  606. id: Date.now(),
  607. invite_code: this.agentForm.invite_code || '',
  608. pc_agent_link: '',
  609. h5_agent_link: '',
  610. login_status: 0,
  611. login_time: ''
  612. })
  613. this.tableData.unshift(row)
  614. this.total += 1
  615. this.$message.success('新增成功')
  616. } else {
  617. this.tableData = this.tableData.map(item => {
  618. return item.id === this.agentForm.id ? Object.assign({}, item, this.agentForm) : item
  619. })
  620. this.$message.success('修改成功')
  621. }
  622. this.agentDialogVisible = false
  623. })
  624. },
  625. resetAgentForm() {
  626. if (this.$refs.agentForm) {
  627. this.$refs.agentForm.resetFields()
  628. }
  629. },
  630. handleBindDomain(row) {
  631. this.domainForm = {
  632. id: row.id,
  633. pc_agent_link: row.pc_agent_link || '',
  634. h5_agent_link: row.h5_agent_link || ''
  635. }
  636. this.domainDialogVisible = true
  637. },
  638. submitDomain() {
  639. this.tableData = this.tableData.map(item => {
  640. return item.id === this.domainForm.id ? Object.assign({}, item, this.domainForm) : item
  641. })
  642. this.domainDialogVisible = false
  643. this.$message.success('绑定成功')
  644. },
  645. handleAdjustBalance(row) {
  646. this.balanceForm = {
  647. id: row.id,
  648. type: 'plus',
  649. amount: 0,
  650. remark: ''
  651. }
  652. this.balanceDialogVisible = true
  653. this.$nextTick(() => {
  654. this.$refs.balanceForm && this.$refs.balanceForm.clearValidate()
  655. })
  656. },
  657. submitBalance() {
  658. this.$refs.balanceForm.validate(valid => {
  659. if (!valid) return
  660. this.tableData = this.tableData.map(item => {
  661. if (item.id !== this.balanceForm.id) return item
  662. const amount = this.balanceForm.type === 'plus' ? this.balanceForm.amount : -this.balanceForm.amount
  663. return Object.assign({}, item, {
  664. balance: Number(item.balance || 0) + amount
  665. })
  666. })
  667. this.balanceDialogVisible = false
  668. this.$message.success('操作成功')
  669. })
  670. },
  671. handleQuota(row) {
  672. this.activeQuotaAgent = row
  673. this.platformBalances = this.getDefaultPlatformBalances()
  674. this.quotaTransferForm = {
  675. id: row.id,
  676. user_balance: this.formatMoney(row.balance),
  677. transfer_type: '',
  678. platform: '',
  679. amount: ''
  680. }
  681. this.quotaDialogVisible = true
  682. this.$nextTick(() => {
  683. this.$refs.quotaTransferForm && this.$refs.quotaTransferForm.clearValidate()
  684. })
  685. },
  686. formatPlatformBalance(item) {
  687. if (item.balance === null || item.balance === undefined || item.balance === '') return ''
  688. return this.formatMoney(item.balance)
  689. },
  690. refreshUserBalance() {
  691. if (!this.activeQuotaAgent) return
  692. const row = this.tableData.find(item => item.id === this.activeQuotaAgent.id)
  693. this.quotaTransferForm.user_balance = this.formatMoney(row ? row.balance : this.activeQuotaAgent.balance)
  694. this.$message.success('刷新成功')
  695. },
  696. refreshPlatformBalance(platform) {
  697. platform.balance = Number((Math.random() * 10000).toFixed(2))
  698. this.$message.success(`${platform.name}刷新成功`)
  699. },
  700. refreshAllPlatformBalance() {
  701. this.platformBalances = this.platformBalances.map(item => {
  702. return Object.assign({}, item, {
  703. balance: Number((Math.random() * 10000).toFixed(2))
  704. })
  705. })
  706. this.$message.success('一键刷新成功')
  707. },
  708. transferAllOut() {
  709. this.platformBalances = this.platformBalances.map(item => {
  710. return Object.assign({}, item, {
  711. balance: 0
  712. })
  713. })
  714. this.$message.success('一键转出成功')
  715. },
  716. submitQuotaTransfer() {
  717. this.$refs.quotaTransferForm.validate(valid => {
  718. if (!valid) return
  719. const amount = Number(this.quotaTransferForm.amount)
  720. if (!amount || amount <= 0) {
  721. this.$message.error('请输入正确的转账金额')
  722. return
  723. }
  724. const platform = this.platformBalances.find(item => item.key === this.quotaTransferForm.platform)
  725. if (!platform) return
  726. const currentUserBalance = Number(this.quotaTransferForm.user_balance || 0)
  727. const currentPlatformBalance = Number(platform.balance || 0)
  728. if (this.quotaTransferForm.transfer_type === 'in') {
  729. if (currentUserBalance < amount) {
  730. this.$message.error('用户余额不足')
  731. return
  732. }
  733. this.quotaTransferForm.user_balance = this.formatMoney(currentUserBalance - amount)
  734. platform.balance = currentPlatformBalance + amount
  735. } else {
  736. if (currentPlatformBalance < amount) {
  737. this.$message.error('平台余额不足')
  738. return
  739. }
  740. this.quotaTransferForm.user_balance = this.formatMoney(currentUserBalance + amount)
  741. platform.balance = currentPlatformBalance - amount
  742. }
  743. this.tableData = this.tableData.map(item => {
  744. return item.id === this.quotaTransferForm.id
  745. ? Object.assign({}, item, { balance: Number(this.quotaTransferForm.user_balance) })
  746. : item
  747. })
  748. this.$message.success('额度转换成功')
  749. })
  750. },
  751. handleStatusChange(row) {
  752. this.$message.success(row.status === 1 ? '已启用' : '已禁用')
  753. }
  754. }
  755. }
  756. </script>
  757. <style lang="scss" scoped>
  758. .agent-page {
  759. width: 100%;
  760. height: 100%;
  761. padding: 16px;
  762. overflow: hidden;
  763. background: #f3f6f8;
  764. }
  765. .agent-panel {
  766. display: flex;
  767. flex-direction: column;
  768. height: 100%;
  769. padding: 20px 20px 12px;
  770. overflow: hidden;
  771. background: #fff;
  772. }
  773. .agent-search {
  774. flex-shrink: 0;
  775. padding-bottom: 8px;
  776. ::v-deep .el-form-item {
  777. margin-right: 22px;
  778. margin-bottom: 14px;
  779. }
  780. ::v-deep .el-form-item__label {
  781. color: #303133;
  782. font-weight: 500;
  783. }
  784. ::v-deep .el-input,
  785. ::v-deep .el-select {
  786. width: 236px;
  787. }
  788. ::v-deep .el-date-editor--daterange.el-input__inner {
  789. width: 400px;
  790. }
  791. }
  792. .search-actions {
  793. margin-right: 0;
  794. ::v-deep .el-form-item__content {
  795. display: flex;
  796. gap: 10px;
  797. }
  798. }
  799. .agent-table {
  800. flex: 1;
  801. min-height: 0;
  802. ::v-deep th {
  803. height: 44px;
  804. background: #fff;
  805. color: #7b8794;
  806. font-weight: 600;
  807. }
  808. ::v-deep td {
  809. height: 136px;
  810. color: #334155;
  811. }
  812. ::v-deep .agent-row-tint td {
  813. background: #e9fbfb;
  814. }
  815. ::v-deep .el-table__fixed-right::before,
  816. ::v-deep .el-table__fixed::before {
  817. background-color: #ebeef5;
  818. }
  819. }
  820. .link-cell {
  821. white-space: normal;
  822. word-break: break-all;
  823. line-height: 1.55;
  824. }
  825. .row-actions {
  826. display: flex;
  827. flex-wrap: wrap;
  828. justify-content: center;
  829. gap: 6px 14px;
  830. .el-button {
  831. margin: 0;
  832. color: #05a58f;
  833. font-weight: 600;
  834. }
  835. }
  836. .agent-pagination {
  837. flex-shrink: 0;
  838. padding-top: 12px;
  839. text-align: right;
  840. }
  841. .full-input {
  842. width: 100%;
  843. }
  844. ::v-deep .quota-dialog {
  845. margin-top: 4vh !important;
  846. .el-dialog__header {
  847. padding: 20px 20px 10px;
  848. }
  849. .el-dialog__body {
  850. padding: 28px 30px 34px;
  851. max-height: 78vh;
  852. overflow-y: auto;
  853. }
  854. }
  855. .quota-content {
  856. width: 100%;
  857. }
  858. .quota-transfer-form {
  859. ::v-deep .el-form-item {
  860. margin-right: 10px;
  861. margin-bottom: 20px;
  862. }
  863. ::v-deep .el-form-item__label {
  864. color: #303133;
  865. }
  866. ::v-deep .el-input,
  867. ::v-deep .el-select {
  868. width: 140px;
  869. }
  870. }
  871. .quota-top-row,
  872. .quota-transfer-row {
  873. display: flex;
  874. align-items: flex-start;
  875. flex-wrap: wrap;
  876. }
  877. .quota-top-row {
  878. margin-bottom: 2px;
  879. ::v-deep .el-form-item:first-child .el-input {
  880. width: 300px;
  881. }
  882. }
  883. .quota-transfer-row {
  884. .el-button--success {
  885. background: #55c333;
  886. border-color: #55c333;
  887. }
  888. }
  889. .platform-grid {
  890. display: grid;
  891. grid-template-columns: repeat(5, 150px);
  892. gap: 30px;
  893. justify-content: start;
  894. padding-top: 10px;
  895. }
  896. .platform-card {
  897. height: 80px;
  898. overflow: hidden;
  899. border: 1px solid #e4e7ed;
  900. border-radius: 4px;
  901. background: #fff;
  902. box-shadow: 0 5px 14px rgba(0, 0, 0, 0.16);
  903. }
  904. .platform-refresh {
  905. display: grid;
  906. grid-template-columns: 1fr 56px;
  907. height: 36px;
  908. ::v-deep .el-input__inner {
  909. height: 36px;
  910. border: 0;
  911. border-right: 1px solid #dcdfe6;
  912. border-bottom: 1px solid #dcdfe6;
  913. border-radius: 0;
  914. color: #606266;
  915. }
  916. .el-button {
  917. height: 36px;
  918. padding: 0;
  919. border: 0;
  920. border-bottom: 1px solid #dcdfe6;
  921. border-radius: 0;
  922. background: #f8fafc;
  923. color: #8a97a6;
  924. }
  925. }
  926. .platform-name {
  927. display: flex;
  928. align-items: center;
  929. justify-content: center;
  930. height: 44px;
  931. color: #ff0000;
  932. font-size: 12px;
  933. font-weight: 700;
  934. }
  935. @media (max-width: 1280px) {
  936. .agent-search {
  937. ::v-deep .el-input,
  938. ::v-deep .el-select {
  939. width: 190px;
  940. }
  941. ::v-deep .el-date-editor--daterange.el-input__inner {
  942. width: 330px;
  943. }
  944. }
  945. .platform-grid {
  946. grid-template-columns: repeat(4, 150px);
  947. }
  948. }
  949. </style>