index.php 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106
  1. <style>
  2. .table-body {
  3. padding: 20px 20px;
  4. background-color: #fff;
  5. }
  6. .table-body .top-input {
  7. margin-top: 34px;
  8. }
  9. .input-item {
  10. width: 200px;
  11. margin-right: 20px;
  12. }
  13. .input-item .el-input__inner {
  14. border-right: 0;
  15. }
  16. .input-item .el-input__inner:hover {
  17. border: 1px solid #dcdfe6;
  18. border-right: 0;
  19. outline: 0;
  20. }
  21. .input-item .el-input__inner:focus {
  22. border: 1px solid #dcdfe6;
  23. border-right: 0;
  24. outline: 0;
  25. }
  26. .input-item .el-input-group__append {
  27. background-color: #fff;
  28. border-left: 0;
  29. width: 10%;
  30. padding: 0;
  31. }
  32. .input-item .el-input-group__append .el-button {
  33. padding: 0;
  34. }
  35. .input-item .el-input-group__append .el-button {
  36. margin: 0;
  37. }
  38. /* #app .table-body .el-table .el-button {
  39. border-radius: 16px;
  40. } */
  41. .create {
  42. height: 36px;
  43. line-height: 36px;
  44. float: right;
  45. color: #BCBCBC;
  46. margin-left: 20px;
  47. }
  48. .name {
  49. cursor: pointer;
  50. color: #49A9FF;
  51. }
  52. /* 卡片 */
  53. .plugin-list {
  54. margin: 0 0 0 -20px;
  55. /* padding-right: 100px; */
  56. display: flex;
  57. flex-wrap: wrap;
  58. }
  59. .plugin-list .plugin-item {
  60. width: 20%;
  61. min-width: 400px;
  62. }
  63. .plugin-item {
  64. border: 1px solid #ebebeb;
  65. background: #FFFFFF;
  66. box-shadow: 3px 5px 15px rgba(80, 80, 80, 0.16);
  67. opacity: 1;
  68. border-radius: 5px;
  69. padding: 20px;
  70. margin: 0 0 20px 20px;
  71. transition: 250ms;
  72. position: relative;
  73. /* min-width: 300px; */
  74. }
  75. .plugin-item .item-status {
  76. position: absolute;
  77. top: 0;
  78. right: 0;
  79. width: 94px;
  80. height: 30px;
  81. background: #E8EAEC;
  82. opacity: 1;
  83. border-radius: 0px 5px 0px 5px;
  84. font-size: 14px;
  85. font-family: Microsoft YaHei;
  86. font-weight: 400;
  87. line-height: 30px;
  88. color: #9398A4;
  89. text-align: center;
  90. }
  91. .item-status-permanent {
  92. width: 94px;
  93. }
  94. .item-status-effective {
  95. width: 164px;
  96. }
  97. .plugin-item .item-info {
  98. display: flex;
  99. align-items: center;
  100. }
  101. /* .plugin-item .item-info .item-right{
  102. min-width: 500px;
  103. } */
  104. .plugin-item .item-btns {
  105. display: flex;
  106. align-items: center;
  107. justify-content: flex-end;
  108. margin-top: 12px;
  109. }
  110. .plugin-item .mall-logo {
  111. width: 70px;
  112. height: 70px;
  113. margin-right: 12px;
  114. }
  115. .plugin-item .mall-logo img {
  116. width: 100%;
  117. height: 100%;
  118. display: block;
  119. border-radius: 50%;
  120. }
  121. .plugin-item .display-name {
  122. font-size: 18pt;
  123. margin-top: 10px;
  124. margin-bottom: 4px;
  125. font-family: Microsoft YaHei;
  126. font-weight: bold;
  127. line-height: 30px;
  128. color: #3F495D;
  129. opacity: 1;
  130. width: 200px;
  131. white-space: nowrap;
  132. overflow: hidden;
  133. text-overflow: ellipsis;
  134. }
  135. .plugin-item .name {
  136. color: #909399;
  137. }
  138. .plugin-item:hover {
  139. cursor: pointer;
  140. border-color: #bfddff;
  141. }
  142. .notinstall .el-checkbox.is-bordered+.el-checkbox.is-bordered {
  143. margin:5px 10px 5px 0px;
  144. }
  145. .notinstall .el-checkbox {
  146. margin-right: 10px;
  147. }
  148. </style>
  149. <div id="app" v-cloak>
  150. <el-card shadow="never" style="border:0" body-style="background-color: #f3f3f3;padding: 0;">
  151. <div slot="header" style="margin-top: 20px;" v-if="!isInd">
  152. <div>
  153. <span>小程序管理</span>
  154. </div>
  155. </div>
  156. <div class="table-body">
  157. <div v-if="isInd">
  158. <el-button type="primary" size="small" @click="showCreateMallDialog()">新建商城
  159. </el-button>
  160. </div>
  161. <br>
  162. <el-form :inline="true" size="small" class="demo-form-inline">
  163. <el-form-item label="">
  164. <el-input @keyup.enter.native="search" size="small" placeholder="请输入商城名称" type="text" clearable @clear="search" v-model="searchForm.keyword">
  165. <el-button slot="append" @click="search" icon="el-icon-search"></el-button>
  166. </el-input>
  167. </el-form-item>
  168. <el-form-item label="">
  169. <el-input @keyup.enter.native="search" size="small" placeholder="请输入手机号" type="text" clearable @clear="search" v-model="searchForm.mobile">
  170. <el-button slot="append" @click="search" icon="el-icon-search"></el-button>
  171. </el-input>
  172. </el-form-item>
  173. <el-form-item label="">
  174. <el-date-picker
  175. v-model="searchForm.date"
  176. type="date"
  177. placeholder="选择日期"
  178. @change="search"
  179. >
  180. </el-date-picker>
  181. </el-form-item>
  182. </el-form>
  183. <div class="plugin-list" v-loading="loading">
  184. <template v-for="(plugin,index) in list">
  185. <!-- <el-col> -->
  186. <div class="plugin-item">
  187. <!-- <div class="plugin-item" @click="entryPlugin(plugin)"> -->
  188. <div v-if="plugin.adonsComboRelation && addons_combo_data && addons_combo_data[plugin.adonsComboRelation.addons_combo_id]" class="item-status" style="overflow: hidden;">{{ addons_combo_data[plugin.adonsComboRelation.addons_combo_id] }}</div>
  189. <div class="item-info">
  190. <div class="mall-logo">
  191. <img :src="plugin.logo" alt="">
  192. </div>
  193. <div class="item-right">
  194. <div class="display-name">{{plugin.name}}</div>
  195. <div flex="box:last">
  196. <div class="name" v-if="plugin.admin">使用者:{{plugin.admin.username}}</div>
  197. </div>
  198. <div flex="box:last">
  199. <div class="name">ID:{{plugin.id}}</div>
  200. </div>
  201. <div flex="box:last">
  202. <div class="name">签名:{{plugin.mall_sign}}</div>
  203. </div>
  204. <div flex="box:last">
  205. <div v-if="plugin.expired_at=='0'" class="name">期限:永久</div>
  206. <div v-else class="name">期限:{{plugin.expired_at|filterDate}}</div>
  207. </div>
  208. </div>
  209. </div>
  210. <div class="item-btns">
  211. <el-button size="mini" style="border:none;color: #9398A4;" id="copyBtn" @click="clickCopyBtn(plugin.mall_info, $event)">复制
  212. </el-button>
  213. <el-button size="mini" @click="toRecycle(plugin)" style="border:none;color: #9398A4;" slot="reference">删除
  214. </el-button>
  215. <!-- <el-button plain size="mini" @click="switchAbleStatus(plugin)"
  216. :type="plugin.is_disable == 0 ? 'danger' : 'primary'" slot="reference">
  217. {{plugin.is_disable == 0 ? '禁用' : '启用'}}
  218. </el-button> -->
  219. <el-button style="border:none;color: #9398A4;" size="mini" @click="edit(plugin)">编辑</el-button>
  220. <el-button style="border:none;color: #9398A4;" size="mini" @click="customHost(plugin)" v-if="has_subdomain">域名</el-button>
  221. <el-button type="primary" size="mini" @click="toEnter(plugin)" >进入商城
  222. </div>
  223. </div>
  224. <!-- </el-col> -->
  225. </template>
  226. </div>
  227. <div style="text-align: right;margin: 20px 0;">
  228. <el-pagination @current-change="pageChange" background layout="prev, pager, next" :page-count="page_count"></el-pagination>
  229. </div>
  230. </div>
  231. </el-card>
  232. <!-- 创建/编辑商城 -->
  233. <el-dialog :title="isEdit==0?'创建商城':'编辑商城'" :visible.sync="createMallDialogVisible" width="40%" :close-on-click-modal="false" @close="closePop">
  234. <el-form label-width="100px" size="small" :model="createMallForm" :rules="createMallRules" ref="createMallForm">
  235. <el-form-item label="商城名称" prop="name">
  236. <el-input type="text" size="small" v-model="createMallForm.name" autocomplete="off"></el-input>
  237. </el-form-item>
  238. <el-form-item prop="logo" v-if="isEdit==1">
  239. <!-- <label slot="label">-->
  240. <!-- <span>商城logo</span>-->
  241. <!-- </label>-->
  242. <!-- <com-attachment v-model="createMallForm.logo" :simple="true">-->
  243. <!-- <el-button>上传图片</el-button>-->
  244. <!-- </com-attachment>-->
  245. <div class="customize-share-title">
  246. <com-image mode="aspectFill" width='80px' height='80px' :src="createMallForm.logo ? createMallForm.logo : ''"></com-image>
  247. <!-- <el-button v-if="createMallForm.logo" class="del-btn" size="mini" type="danger" icon="el-icon-close" circle @click="createMallForm.logo = ''"></el-button>-->
  248. </div>
  249. <!-- <el-button @click="app_share.dialog = true;app_share.type = 'pic_bg'"
  250. type="text">查看图例
  251. </el-button> -->
  252. </el-form-item>
  253. <el-form-item label="商城有效期" prop="expired_at" ref="expired_at">
  254. <el-date-picker type="datetime" v-if="isCheckExpired" :disabled="true"></el-date-picker>
  255. <el-date-picker v-else :picker-options="pickerOptions" :disabled="isCheckExpired" type="datetime" value-format="yyyy-MM-dd HH:mm:ss" placeholder="选择日期" v-model="createMallForm.expired_at">
  256. </el-date-picker>
  257. <el-checkbox v-model="isCheckExpired" @change="checkExpiredAt">永久</el-checkbox>
  258. </el-form-item>
  259. <el-form-item label="手机号码" prop="mobile" v-if="isEdit==0">
  260. <el-input type="text" size="small" v-model="createMallForm.mobile" autocomplete="off"></el-input>
  261. </el-form-item>
  262. <!-- 应用付费套餐绑定 -->
  263. <el-form-item label="选择套餐" prop="addons_combo_id" v-if="admin_type == 1 && isEdit==0 && addons_combo.length>0">
  264. <el-select v-model="createMallForm.addons_combo_id" placeholder="请选择套餐">
  265. <el-option
  266. v-for="item in addons_combo"
  267. :key="item.id"
  268. :label="item.title"
  269. :value="item.id">
  270. </el-option>
  271. </el-select>
  272. </el-form-item>
  273. <!-- 重置登录密码 -->
  274. <el-form-item label="登录密码" prop="password" v-if="admin_type == 1">
  275. <el-input type="password" size="small" v-model="createMallForm.password"></el-input>
  276. </el-form-item>
  277. <el-form-item label="套餐名称" prop="addons_combo_id" v-if="isEdit!=0 && addons_combo.length>0 && addons_combo_name">
  278. {{addons_combo_name}}
  279. </el-form-item>
  280. <el-form-item label="同步示例商城数据" v-if="isEdit==0">
  281. <el-switch v-model="createMallForm.is_sync_mall_data" :active-value="1" :inactive-value="0">
  282. </el-switch>
  283. </el-form-item>
  284. <el-form-item label="合规模式">
  285. <el-switch v-model="createMallForm.is_compliance" :active-value="1" :inactive-value="0">
  286. </el-switch>
  287. </el-form-item>
  288. <!-- 应用付费套餐绑定 -->
  289. <el-form-item label="显示版权">
  290. <el-switch v-model="createMallForm.is_show_copyright" :active-value="1" :inactive-value="0">
  291. </el-switch>
  292. </el-form-item>
  293. <el-form-item label="客服电话" prop="contact_tel">
  294. <el-input type="text" size="small" v-model="createMallForm.contact_tel" autocomplete="off"></el-input>
  295. </el-form-item>
  296. <!-- 增加套餐 -->
  297. <el-form-item v-if="createMallForm.id && admin_type == 1" label="安装套餐" prop="install_addons" class="notinstall">
  298. <el-checkbox-group v-model="createMallForm.install_addons">
  299. <el-collapse v-model="activeCollapse">
  300. <el-collapse-item v-for="(item, key) in notinstall_addons" :key="key" :title="item.title" :name="key">
  301. <el-checkbox class="addons-item"
  302. v-for="(addon, index) in item.list"
  303. :key="index"
  304. :checked="item.check"
  305. size="medium"
  306. :label="addon.name"
  307. border>{{ addon.title }}</el-checkbox>
  308. </el-collapse-item>
  309. </el-collapse>
  310. </el-checkbox-group>
  311. </el-form-item>
  312. <el-form-item style="text-align: right">
  313. <el-button size="small" @click="createMallDialogVisible = false">取消</el-button>
  314. <el-button size="small" :loading="createMallSubmitLoading" type="primary" @click="createMallSubmit('createMallForm')">确定
  315. </el-button>
  316. </el-form-item>
  317. </el-form>
  318. </el-dialog>
  319. <!-- 修改版权 -->
  320. <el-dialog title="修改版权" :visible.sync="copyrightDialogVisible">
  321. <el-form label-width="130px" v-if="copyrightForm" :model="copyrightForm">
  322. <el-form-item label="底部版权文字">
  323. <el-input style="width: 70%" type="textarea" autosize size="small" v-model="copyrightForm.description" autocomplete="off"></el-input>
  324. </el-form-item>
  325. <el-form-item label="底部版权图标">
  326. <com-attachment v-model="copyrightForm.pic_url" :simple="true">
  327. <el-tooltip class="item" effect="dark" content="建议尺寸:160*50" placement="top">
  328. <el-button size="small">选择图片</el-button>
  329. </el-tooltip>
  330. </com-attachment>
  331. <com-image width="80px" height="80px" mode="aspectFill" :src="copyrightForm.pic_url"></com-image>
  332. </el-form-item>
  333. <el-form-item label="底部版权链接">
  334. <el-input style="width: 70%" placeholder="请选择链接" size="small" disabled v-model="copyrightForm.link_url">
  335. <com-pick-link slot="append" :mall-id="copyrightForm.mall_id" @selected="selectAdvertUrl">
  336. <el-button size="mini">选择链接</el-button>
  337. </com-pick-link>
  338. </el-input>
  339. </el-form-item>
  340. <el-form-item style="text-align: right">
  341. <el-button size="small" @click="copyrightDialogVisible = false">取消</el-button>
  342. <el-button size="small" type="primary" @click="copyrightSubmit()" :loading="copyrightSubmitLoading">确定
  343. </el-button>
  344. </el-form-item>
  345. </el-form>
  346. </el-dialog>
  347. <!-- 迁移 -->
  348. <el-dialog title="选择所属账户" :visible.sync="changeOwnerDialogVisible" width="30%">
  349. <div style="margin-bottom: 10px;">当前迁移的商城:<span style="color: #ff4544">{{currentChangeOwnerMall.name}}</span>
  350. </div>
  351. <div class="search-input-item">
  352. <el-input size="small" placeholder="请输入搜索内容" type="text" clearable @clear="loadAdminList" v-model="keyword">
  353. <el-button slot="append" @click="loadAdminList" icon="el-icon-search"></el-button>
  354. </el-input>
  355. </div>
  356. <el-table v-loading="adminListLoading" :data="adminList" style="margin-bottom: 20px;">
  357. <el-table-column align="center" prop="id" label="id"></el-table-column>
  358. <el-table-column align="center" prop="nickname" label="用户名"></el-table-column>
  359. <el-table-column align="center" label="操作">
  360. <template slot-scope="scope">
  361. <el-button :loading="scope.row.loading" plain size="mini" type="primary" @click="changeToOwner(scope.row)">选择
  362. </el-button>
  363. </template>
  364. </el-table-column>
  365. </el-table>
  366. <!-- 分页器 -->
  367. <el-pagination v-if="adminListPagination" style="text-align: center" background @current-change="adminListPageChange" layout="prev, pager, next" :page-count="adminListPagination.page_count">
  368. </el-pagination>
  369. </el-dialog>
  370. <!-- 操作类提示 -->
  371. <el-dialog title="提示" :visible.sync="dialogOperation" width="30%">
  372. <span>这是一段信息</span>
  373. <span slot="footer" class="dialog-footer">
  374. <el-button @click="dialogVisible = false">取 消</el-button>
  375. <el-button type="primary" @click="dialogVisible = false">确 定</el-button>
  376. </span>
  377. </el-dialog>
  378. <el-dialog title="自定义域名" :visible.sync="customHostDialogVisible" width="40%" :close-on-click-modal="false" @close="closeCustomHost">
  379. <el-form label-width="100px" size="small" :model="customHostForm" :rules="customHostRules" ref="hostForm">
  380. <el-form-item label="启用">
  381. <el-switch v-model="customHostForm.is_custom_host" :active-value="1" :inactive-value="0">
  382. </el-switch>
  383. </el-form-item>
  384. <el-form-item label="后台域名" prop="backend_url">
  385. <el-input type="text" size="small" v-model="customHostForm.backend_url" autocomplete="off"></el-input>
  386. </el-form-item>
  387. <el-form-item label="h5域名" prop="h5_url">
  388. <el-input type="text" size="small" v-model="customHostForm.h5_url" autocomplete="off"></el-input>
  389. </el-form-item>
  390. <el-form-item label="api域名" prop="api_url">
  391. <el-input type="text" size="small" v-model="customHostForm.api_url" autocomplete="off"></el-input>
  392. </el-form-item>
  393. <el-form-item label="静态域名" prop="api_url">
  394. <el-input type="text" size="small" v-model="customHostForm.static_url" autocomplete="off"></el-input>
  395. </el-form-item>
  396. <el-form-item label="证书" prop="ssl_path">
  397. <el-input placeholder="请输入内容" v-model="customHostForm.ssl_path" disabled>
  398. <template slot="append">
  399. <el-upload
  400. action="/index.php?r=admin/file/upload"
  401. multiple
  402. :show-file-list="false"
  403. accept=".zip"
  404. :on-success="handleAvatarSuccess"
  405. >
  406. <el-button>点击上传</el-button>
  407. </el-upload>
  408. </template>
  409. </el-input>
  410. </el-form-item>
  411. <el-form-item style="text-align: right">
  412. <el-button size="small" @click="customHostDialogVisible = false">取消</el-button>
  413. <el-button size="small" type="primary" @click="customHostSubmit('hostForm')">确定
  414. </el-button>
  415. </el-form-item>
  416. </el-form>
  417. </el-dialog>
  418. </div>
  419. <script>
  420. new Vue({
  421. el: '#app',
  422. data() {
  423. return {
  424. admin_type:0,
  425. pickerOptions: {
  426. disabledDate(time) {
  427. return time.getTime() < Date.now() - 8.64e7
  428. }
  429. },
  430. isInd: _isInd,
  431. notinstall_addons:[],
  432. activeCollapse:[],
  433. addons_combo_data:[],
  434. addons_combo_name:'',
  435. isAdmin: _isAdmin,
  436. isSuperAdmin: _isSuperAdmin,
  437. createMallDialogVisible: false,
  438. keyword: '',
  439. isEdit: 0, //默认不是编辑
  440. createMallForm: {
  441. id: 0,
  442. name: '',
  443. contact_tel: '',
  444. mobile: '',
  445. password: '',
  446. logo: '',
  447. expired_at: '',
  448. addons_combo_id: null,
  449. is_compliance: 0,
  450. is_show_copyright: 0,
  451. install_addons: [],
  452. is_sync_mall_data: 0,
  453. },
  454. isCheckExpired: false,
  455. isExpiredDisabled: false,
  456. createMallRules: {
  457. name: [{
  458. required: true,
  459. message: '请填写商城名称。'
  460. }, ],
  461. mobile: [
  462. {
  463. required: true,
  464. validator: (rule, value, callback) => {
  465. if(value==''){
  466. callback('请输入手机号');
  467. return
  468. }
  469. if(!(/^1\d{10}$/.test(value))){
  470. callback('手机号码有误,请重填');
  471. }
  472. callback();
  473. }
  474. }
  475. ],
  476. expired_at: [{
  477. required: true,
  478. message: '请选择商城有效期'
  479. }, ]
  480. },
  481. createMallSubmitLoading: false,
  482. adminInfo: {},
  483. searchForm: {
  484. keyword: '',
  485. mobile: '',
  486. date: '',
  487. },
  488. searchLoading: false,
  489. list: [],
  490. page_count: null,
  491. loading: false,
  492. toRecycleLoading: false,
  493. copyrightDialogVisible: false,
  494. copyrightForm: null,
  495. copyrightSubmitLoading: false,
  496. switchAbleStatusLoading: false,
  497. changeOwnerDialogVisible: false,
  498. currentChangeOwnerMall: {
  499. name: ''
  500. },
  501. adminListForm: {
  502. page: 0,
  503. },
  504. adminListLoading: false,
  505. adminList: null,
  506. adminListPagination: null,
  507. mallListPage: 1, //默认请求第一页数据
  508. user: _baseUrl + '/resources/img/admin/mall-logo.png',
  509. list: [],
  510. dialogOperation: false, //操作弹窗显示状态
  511. TitleOperation: false, //操作标题
  512. addons_combo:[],
  513. customHostDialogVisible: false,
  514. customHostForm: {
  515. backend_url: '',
  516. h5_url: '',
  517. api_url: '',
  518. static_url: '',
  519. is_custom_host: 0,
  520. ssl_path: '',
  521. },
  522. customHostRules: {
  523. backend_url: [{
  524. required: true,
  525. message: '请填写后台域名。'
  526. },
  527. ],
  528. h5_url: [
  529. {
  530. required: true,
  531. message: '请填写h5域名。'
  532. },
  533. ],
  534. api_url: [
  535. {
  536. required: true,
  537. message: '请填写api域名。'
  538. },
  539. ],
  540. static_url: [
  541. {
  542. required: true,
  543. message: '请填写静态域名。'
  544. },
  545. ],
  546. ssl_path: [
  547. {
  548. required: true,
  549. message: '请上传您的域名证书。'
  550. },
  551. ],
  552. },
  553. customHostSubmitLoading: false,
  554. has_subdomain: <?php echo $has_subdomain; ?>,
  555. mallId: '',
  556. }
  557. },
  558. created() {
  559. this.loadList({});
  560. this.expireNotice()
  561. this.serverNotice()
  562. },
  563. methods: {
  564. // 0.1 新建商城
  565. showCreateMallDialog() {
  566. this.isEdit = 0;
  567. this.createMallDialogVisible = true;
  568. this.createMallForm.name = '';
  569. this.createMallForm.expired_at = '';
  570. this.createMallForm.contact_tel = '';
  571. this.createMallForm.id = null;
  572. this.isCheckExpired = false;
  573. this.install_addons = [];
  574. },
  575. // 确认编辑/新增
  576. createMallSubmit(formName) {
  577. this.$refs[formName].validate(valid => {
  578. if (valid) {
  579. this.createMallSubmitLoading = true;
  580. this.$refs['expired_at'].clearValidate();
  581. console.log(this.createMallForm, '============');
  582. this.$request({
  583. params: {
  584. r: 'admin/mall/create',
  585. },
  586. method: 'post',
  587. data: this.createMallForm,
  588. }).then(e => {
  589. console.log(e, "创建成功")
  590. this.createMallSubmitLoading = false;
  591. if (e.data.code === 0) {
  592. this.createMallDialogVisible = false;
  593. this.$message.success(e.data.msg);
  594. this.createMallForm = {
  595. id: null,
  596. name: '',
  597. logo: '',
  598. expired_at: '',
  599. install_addons: [],
  600. }
  601. this.loadList({
  602. page: this.mallListPage
  603. });
  604. // 更新当前item数据
  605. } else {
  606. this.$message.error(e.data.msg);
  607. }
  608. }).catch(e => {
  609. console.log(e, "失败了?")
  610. });
  611. } else {}
  612. });
  613. },
  614. // 2.0 获取列表数据
  615. loadList(params) {
  616. params['r'] = 'admin/mall/index';
  617. params['keyword'] = this.searchForm.keyword;
  618. params['mobile'] = this.searchForm.mobile;
  619. params['date'] = this.searchForm.date;
  620. params['is_recycle'] = this.searchForm.isRecycle;
  621. params['user_id'] = getQuery('user_id');
  622. params['page'] = this.mallListPage;
  623. params['limit'] = 12;
  624. this.searchLoading = true;
  625. this.$request({
  626. params: params,
  627. }).then(e => {
  628. this.searchLoading = false;
  629. if (e.data.code === 0) {
  630. for (let i in e.data.data.list) {
  631. e.data.data.list[i].recyclePopoverVisible = false;
  632. e.data.data.list[i].ableStatusPopoverVisible = false;
  633. }
  634. this.list = e.data.data.list;
  635. this.admin_type = e.data.data.admin_type;
  636. this.page_count = e.data.data.page_count;
  637. this.adminInfo = e.data.data.admin_info;
  638. this.addons_combo_data = e.data.data.addons_combo_data;
  639. //console.log(this.admin_type,55);
  640. this.showCopyright = e.data.data.showCopyright;
  641. if (!isEmpty(e.data.data.addons_combo)) this.addons_combo = e.data.data.addons_combo;
  642. }
  643. }).catch(e => {});
  644. },
  645. search() {
  646. this.loadList({});
  647. },
  648. pageChange(page) {
  649. this.mallListPage = page;
  650. this.loadList({
  651. page: page,
  652. });
  653. },
  654. toEnter(row) {
  655. localStorage.clear();
  656. this.$request({
  657. params: {
  658. r: 'admin/mall/entry'
  659. },
  660. method: 'post',
  661. data: {
  662. mall_id: row.id
  663. }
  664. }).then(e => {
  665. if (e.data.code === 0) {
  666. this.clearMenuStorage();
  667. this.$navigate(e.data.data.redirect_url);
  668. } else {
  669. this.$message.error(e.data.msg);
  670. }
  671. });
  672. },
  673. clearMenuStorage() {
  674. localStorage.removeItem('open_menu_1_id');
  675. localStorage.removeItem('open_menu_2_id');
  676. localStorage.removeItem('open_menu_3_id');
  677. localStorage.removeItem('unfold_id_1');
  678. localStorage.removeItem('unfold_id_2');
  679. },
  680. // 删除
  681. toRecycle(row) {
  682. this.$confirm('删除该条数据后不可以恢复, 是否继续?', '警告', {type: 'warning'}).then(() => {
  683. this.toRecycleLoading = true;
  684. this.$request({
  685. params: {r: 'admin/mall/update'},
  686. method: 'post',
  687. data: {is_recycle: 1, id: row.id},
  688. }).then(e => {
  689. this.toRecycleLoading = false;
  690. if (e.data.code === 0) {
  691. this.$message.success(e.data.msg);
  692. row.recyclePopoverVisible = false;
  693. this.loadList({});
  694. } else {
  695. this.$message.error(e.data.msg);
  696. }
  697. }).catch(e => {
  698. });
  699. });
  700. },
  701. clickCopyBtn: function (text, event) {
  702. const btnId = '#' + event.currentTarget.id;
  703. const clipboard = new ClipboardJS(btnId, {
  704. text: () => text
  705. });
  706. // const clipboard = new ClipboardJS(event.target);
  707. clipboard.on("success", e => {
  708. this.$message({
  709. type: "success",
  710. message: "商城账号信息复制成功",
  711. showClose: true,
  712. }); //这里你如果引入了elementui的提示就可以用,没有就注释即可
  713. // 释放内存
  714. clipboard.destroy();
  715. });
  716. clipboard.on("error", e => {
  717. // 不支持复制
  718. this.$message({
  719. type: "error",
  720. message: "商城账号信息复制失败",
  721. showClose: true,
  722. });
  723. clipboard.destroy();
  724. });
  725. },
  726. showCopyrightDialog(row) {
  727. if (row.copyright) {
  728. this.copyrightForm = row.copyright;
  729. this.copyrightForm.mall_id = row.id;
  730. } else {
  731. this.copyrightForm = {
  732. description: '',
  733. link_url: '',
  734. pic_url: null,
  735. type: 1,
  736. mobile: '',
  737. mall_id: row.id,
  738. link: ''
  739. };
  740. }
  741. this.copyrightDialogVisible = true;
  742. },
  743. copyrightSubmit() {
  744. this.copyrightSubmitLoading = true;
  745. this.copyrightForm['id'] = this.copyrightForm.mall_id;
  746. this.$request({
  747. params: {r: 'admin/mall/set-copyright'},
  748. method: 'post',
  749. data: this.copyrightForm,
  750. }).then(e => {
  751. this.copyrightSubmitLoading = false;
  752. if (e.data.code === 0) {
  753. this.copyrightDialogVisible = false;
  754. this.$message.success(e.data.msg);
  755. this.loadList({});
  756. } else {
  757. this.$message.error(e.data.msg);
  758. }
  759. }).catch(e => {});
  760. },
  761. switchAbleStatus(row) {
  762. this.switchAbleStatusLoading = true;
  763. this.$request({
  764. params: {r: 'admin/mall/disable',id: row.id,status: 1},
  765. method: 'get'
  766. }).then(e => {
  767. this.switchAbleStatusLoading = false;
  768. if (e.data.code === 0) {
  769. this.$message.success(e.data.msg);
  770. row.ableStatusPopoverVisible = false;
  771. this.loadList({});
  772. } else {
  773. this.$message.error(e.data.msg);
  774. }
  775. }).catch(e => {});
  776. },
  777. selectAdvertUrl(e) {
  778. let self = this;
  779. let link_url;
  780. e.forEach(function(item, index) {
  781. link_url = item.new_link_url;
  782. });
  783. this.copyrightForm.link = e[0];
  784. this.copyrightForm.link_url = link_url;
  785. },
  786. showChangeOwnerDialog(row) {
  787. this.currentChangeOwnerMall = row;
  788. this.changeOwnerDialogVisible = true;
  789. if (!this.adminList) {
  790. this.loadAdminList();
  791. }
  792. },
  793. loadAdminList() {
  794. this.adminListLoading = true;
  795. this.$request({
  796. params: {
  797. r: 'admin/user/index',
  798. page: this.adminListForm.page,
  799. keyword: this.keyword,
  800. is_super_admin: 1,
  801. }
  802. }).then(e => {
  803. this.adminListLoading = false;
  804. if (e.data.code === 0) {
  805. for (let i in e.data.data.list) {
  806. e.data.data.list[i].loading = false;
  807. }
  808. this.adminList = e.data.data.list;
  809. this.adminListPagination = e.data.data.pagination;
  810. } else {}
  811. }).catch(e => {});
  812. },
  813. adminListPageChange(page) {
  814. this.adminListForm.page = page;
  815. this.loadAdminList();
  816. },
  817. changeToOwner(row) {
  818. const content = '确认将`' + this.currentChangeOwnerMall.name + '`迁移至`' + row.username + '`账户下?';
  819. this.$confirm(content, '提示').then(e => {
  820. row.loading = true;
  821. this.$request({
  822. params: {
  823. r: "admin/mall/removal",
  824. user_id: row.id,
  825. mall_id: this.currentChangeOwnerMall.id,
  826. },
  827. }).then(e => {
  828. row.loading = false;
  829. if (e.data.code === 0) {
  830. this.changeOwnerDialogVisible = false;
  831. this.$message.success(e.data.msg);
  832. this.loadList({});
  833. } else {
  834. this.$message.error(e.data.msg);
  835. }
  836. }).catch(e => {});
  837. }).catch(e => {});
  838. },
  839. checkExpiredAt(value) {
  840. this.isCheckExpired = value;
  841. if (value) {
  842. this.createMallForm.expired_at = 0
  843. } else {
  844. this.createMallForm.expired_at = ''
  845. }
  846. this.$refs['expired_at'].clearValidate();
  847. },
  848. edit(row) {
  849. let that = this;
  850. this.isEdit = 1;
  851. // return
  852. this.createMallForm.logo = (!row.logo) ? this.user : row.logo;
  853. this.createMallDialogVisible = true;
  854. this.createMallForm.id = row.id;
  855. this.createMallForm.name = row.name;
  856. this.createMallForm.is_compliance = row.is_compliance;
  857. this.createMallForm.is_show_copyright = row.is_show_copyright;
  858. this.createMallForm.contact_tel = row.contact_tel;
  859. if(row.adonsComboRelation && row.adonsComboRelation.addons_combo_id){
  860. this.addons_combo_name = this.addons_combo_data[row.adonsComboRelation.addons_combo_id];
  861. }else{
  862. this.addons_combo_name = '';
  863. }
  864. if (row.expired_at == 0) {
  865. this.createMallForm.expired_at = row.expired_at;
  866. this.isCheckExpired = true;
  867. } else {
  868. //转为yyyy-MM-dd HH:mm:ss-回显
  869. let date = new Date(row.expired_at * 1000);
  870. let y = date.getFullYear();
  871. let MM = date.getMonth() + 1;
  872. MM = MM < 10 ? ('0' + MM) : MM;
  873. let d = date.getDate();
  874. d = d < 10 ? ('0' + d) : d;
  875. let h = date.getHours();
  876. h = h < 10 ? ('0' + h) : h;
  877. let m = date.getMinutes();
  878. m = m < 10 ? ('0' + m) : m;
  879. let s = date.getSeconds();
  880. s = s < 10 ? ('0' + s) : s;
  881. this.createMallForm.expired_at = y + '-' + MM + '-' + d + ' ' + h + ':' + m + ':' + s;
  882. }
  883. // 获取插件
  884. if (this.addons_combo.length > 0) {
  885. request({
  886. params: {
  887. r: 'admin/addons/get-mall-addons',
  888. mall_id: row.id
  889. },
  890. method: 'get',
  891. }).then(e => {
  892. this.loading = false;
  893. if (e.data.code === 0) {
  894. if (e.data.data) {
  895. this.activeCollapse = [];
  896. this.createMallForm.install_addons = [];
  897. this.notinstall_addons = e.data.data
  898. for (let key in this.notinstall_addons) {
  899. for (let index in this.notinstall_addons[key].list) {
  900. let item = this.notinstall_addons[key].list[index]
  901. if (item.check == true) this.createMallForm.install_addons.push(item.name)
  902. }
  903. this.activeCollapse.push(key)
  904. }
  905. }
  906. } else {
  907. this.$message.error(e.data.msg);
  908. }
  909. }).catch(e => {
  910. });
  911. }
  912. },
  913. closePop(){
  914. this.$refs["createMallForm"].resetFields();
  915. },
  916. customHost(row) {
  917. this.customHostDialogVisible = true;
  918. this.mallId = row.id;
  919. if(row.mallHost) {
  920. this.customHostForm.backend_url = row.mallHost.backend_url;
  921. this.customHostForm.h5_url = row.mallHost.h5_url;
  922. this.customHostForm.api_url = row.mallHost.api_url;
  923. this.customHostForm.static_url = row.mallHost.static_url;
  924. this.customHostForm.is_custom_host = row.mallHost.is_custom_host;
  925. this.customHostForm.ssl_path = row.mallHost.ssl_path;
  926. } else {
  927. this.customHostForm.backend_url = ''
  928. this.customHostForm.h5_url = ''
  929. this.customHostForm.api_url = ''
  930. this.customHostForm.static_url = ''
  931. this.customHostForm.is_custom_host = ''
  932. this.customHostForm.ssl_path = ''
  933. }
  934. },
  935. closeCustomHost() {
  936. this.$refs["hostForm"].resetFields();
  937. },
  938. customHostSubmit(formName) {
  939. this.$refs[formName].validate(valid => {
  940. if (valid) {
  941. this.customHostSubmitLoading = true;
  942. this.$request({
  943. params: {
  944. r: 'admin/mall/custom-host',
  945. mall_id: this.mallId,
  946. },
  947. method: 'post',
  948. data: this.customHostForm,
  949. }).then(e => {
  950. this.customHostSubmitLoading = false;
  951. if (e.data.code === 0) {
  952. this.customHostSubmitLoading = false;
  953. this.$message.success(e.data.msg);
  954. this.customHostDialogVisible = false;
  955. this.loadList({
  956. page: this.mallListPage
  957. });
  958. } else {
  959. this.$message.error(e.data.msg);
  960. }
  961. }).catch(e => {
  962. console.log(e, "失败了?")
  963. });
  964. }
  965. })
  966. },
  967. handleExceed(files, fileList) {
  968. this.$message.warning(`当前限制选择 1 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`);
  969. },
  970. handleAvatarSuccess(res, file) {
  971. if (res.code == 0) {
  972. // let url = URL.createObjectURL(file.raw)
  973. let url = res.data.path
  974. this.customHostForm.ssl_path = url
  975. } else {
  976. this.$message.error(res.msg);
  977. }
  978. },
  979. expireNotice() {
  980. this.$request({
  981. params: {
  982. r: 'admin/expire-notice/certificate-notice',
  983. },
  984. method: 'get',
  985. }).then(e => {
  986. if (e.data.code === 0) {
  987. let data = e.data.data
  988. let notice = ''
  989. data.forEach(item => {
  990. notice += item + ','
  991. })
  992. if (notice) {
  993. notice = notice.substring(0, notice.length - 1)
  994. this.$message({
  995. message: '当前 ' + notice + ' SSL证书即将到期,请及时进行更换,以免造成不必要的损失',
  996. type: 'warning',
  997. duration: 10000,
  998. })
  999. }
  1000. }
  1001. })
  1002. },
  1003. serverNotice() {
  1004. this.$request({
  1005. params: {
  1006. r: 'admin/expire-notice/server-notice',
  1007. },
  1008. method: 'get',
  1009. }).then(e => {
  1010. if (e.data.code === 0 && e.data.data) {
  1011. this.$message({
  1012. message: '当前服务器即将到期,请及时进行续费,以免造成不必要的损失',
  1013. type: 'warning',
  1014. duration: 10000,
  1015. })
  1016. }
  1017. })
  1018. },
  1019. },
  1020. filters: {
  1021. // 只保留年月日
  1022. filterDate(value) {
  1023. var value = parseInt(value)*1000;
  1024. if (value != 0) {
  1025. let valueResult = new Date(value).getTime(); //转毫秒
  1026. let timestamp = Date.parse(new Date()); //当前毫秒时间戳
  1027. let date = new Date(value);
  1028. let y = date.getFullYear();
  1029. let MM = date.getMonth() + 1;
  1030. MM = MM < 10 ? ('0' + MM) : MM;
  1031. let d = date.getDate();
  1032. d = d < 10 ? ('0' + d) : d;
  1033. if (valueResult * 1 > timestamp * 1) {
  1034. return y + '-' + MM + '-' + d;
  1035. } else {
  1036. return '已过期(' + y + '-' + MM + '-' + d + ')';
  1037. }
  1038. }
  1039. },
  1040. },
  1041. });
  1042. </script>