index.html 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  1. <template>
  2. <el-card shadow="never">
  3. <template #header>
  4. {if $plugins_host!='www.56q7.com'}
  5. <el-alert effect="dark" :closable="false">扩展可以为系统提供丰富的功能,支持通过更换扩展服务地址来安装其他开发者的扩展程序,同时你也可以打包好的扩展程序开放给别人使用,如需要开放本地扩展,请下载插件【开放扩展支持】</el-alert>
  6. {else}
  7. <el-alert effect="dark" :closable="false" type="error" title="温馨提醒">您当前未使用官方服务端,为了避免不必要的损失,请勿在正式环境上安装扩展,如有人违法销售涉及“赌博、色情、盗版”等违法扩展程序,<a style="color: #fff;text-decoration: underline;" target="_blank" href="https://bbs.56q7.com/">点击这里举报</a>。</el-alert>
  8. {/if}
  9. </template>
  10. <yun-table
  11. :columns="columns"
  12. :common-search="false"
  13. search="title"
  14. tabs="type"
  15. ref="yuntable"
  16. toolbar="refresh,install,create"
  17. :extend="extend">
  18. <template #toolbar="{tool}">
  19. <template v-if="tool=='install'">
  20. <el-button type="primary" plain class="install hide-600">
  21. <el-radio-group v-model="plain" @change="changePlain">
  22. <el-radio label="all">全部</el-radio>
  23. <el-radio label="free" class="hide-1000">免费</el-radio>
  24. <el-radio label="not-free" class="hide-1000">付费</el-radio>
  25. <el-radio label="local">本地</el-radio>
  26. </el-radio-group>
  27. </el-button>
  28. </template>
  29. <template v-if="tool=='create'">
  30. <el-button type="primary" @click="createAddon">
  31. 创建扩展
  32. </el-button>
  33. </template>
  34. </template>
  35. <template #header="{field}">
  36. <div v-if="field=='packed'">
  37. 打包
  38. <el-tooltip
  39. effect="dark"
  40. content="仅支持打包安装好的扩展"
  41. placement="top-start">
  42. <i class="fa fa-info-circle"></i>
  43. </el-tooltip>
  44. </div>
  45. <div v-if="field=='open'">
  46. 开放
  47. <el-tooltip
  48. effect="dark"
  49. content="打包好的扩展才能开放给其他开发者使用,禁止销售涉及“赌博、色情、盗版”等违法扩展程序,禁止销售未取得版权,其他开发者的付费程序"
  50. placement="top-start">
  51. <i class="fa fa-info-circle"></i>
  52. </el-tooltip>
  53. </div>
  54. </template>
  55. </yun-table>
  56. </el-card>
  57. <el-dialog :width="500" v-model="buyDialog.show" @close="closeBuyDialog" :title="'购买'+type[buyDialog.row.type]+'【'+buyDialog.row.name+'】'">
  58. <div class="paycode">
  59. <el-alert type="warning">购买后,可以通过微信的支付凭证交易单号重复下载,有效期为30天</el-alert>
  60. <img v-if="buyDialog.code_url" :src="buyDialog.code_url" style="width: 150px;height: 150px;"/>
  61. <div style="margin-bottom: 10px;">¥{{buyDialog.row.price}}</div>
  62. </div>
  63. <div class="transaction_id">
  64. <el-input v-model="buyDialog.transaction_id" placeholder="请输入交易单号" @change="checkTransactionId"></el-input>
  65. </div>
  66. <div class="message" v-if="buyDialog.message">
  67. <el-tag type="success" v-if="buyDialog.expire_time>0">{{buyDialog.message}}</el-tag>
  68. <el-tag type="info" v-else>{{buyDialog.message}}</el-tag>
  69. </div>
  70. <div class="footer" v-if="buyDialog.status && buyDialog.expire_time>0">
  71. <el-button size="large" type="primary" style="width: 100%" @click="payDownload">下载</el-button>
  72. </div>
  73. </el-dialog>
  74. </template>
  75. <script>
  76. import table from "@components/Table.js";
  77. import {rand} from "@util.js";
  78. //生成订单号
  79. function create_out_trade_no()
  80. {
  81. let date=new Date();
  82. let year=date.getFullYear();
  83. let month=date.getMonth()+1;
  84. let day=date.getDate();
  85. if(day<10){
  86. day='0'+day;
  87. }
  88. let hour=date.getHours();
  89. if(hour<10){
  90. hour='0'+hour;
  91. }
  92. let minute=date.getMinutes();
  93. if(minute<10){
  94. minute='0'+minute;
  95. }
  96. let seconds=date.getSeconds();
  97. if(seconds<10){
  98. seconds='0'+seconds;
  99. }
  100. let r=''+year+month+day+hour+minute+seconds+rand(10000,99999);
  101. return r;
  102. }
  103. function formatTime(seconds)
  104. {
  105. let interval = Math.floor(seconds / 31536000);
  106. if (interval >= 1) {
  107. return `${interval}年后`;
  108. }
  109. interval = Math.floor(seconds / 2592000);
  110. if (interval >= 1) {
  111. return `${interval}月后`;
  112. }
  113. interval = Math.floor(seconds / 86400);
  114. if (interval >= 1) {
  115. return `${interval}天后`;
  116. }
  117. interval = Math.floor(seconds / 3600);
  118. if (interval >= 1) {
  119. return `${interval}小时后`;
  120. }
  121. interval = Math.floor(seconds / 60);
  122. if (interval >= 1) {
  123. return `${interval}分钟后`;
  124. }
  125. return `${Math.floor(seconds)}秒后`;
  126. }
  127. export default{
  128. components:{'YunTable':table},
  129. data:{
  130. extend:{
  131. index_url: 'addons/index',
  132. multi_url: 'addons/multi'
  133. },
  134. type:Yunqi.data.type,
  135. tabsValue:'plugin',
  136. plain:'all',
  137. columns:[
  138. {field:"plain",visible:'none',operate:{form:'hidden',value:function (){return Yunqi.app.plain},filter:false}},
  139. {field:"name",title:"扩展名称"},
  140. {field:"type",title:"扩展类型",searchList:Yunqi.data.type,operate:false},
  141. {field:"author",title:"作者"},
  142. {field:"price",title:"价格",width: 80,formatter:function (data) {
  143. let tag=Yunqi.formatter.tag;
  144. if (data) {
  145. tag.type='primary';
  146. tag.value='¥'+data;
  147. }else{
  148. tag.type='success';
  149. tag.value='免费';
  150. }
  151. return tag;
  152. }},
  153. {field:"version",title:"版本号",width: 80},
  154. {field:"document",title:"说明文档",formatter: function (data){
  155. if(data) {
  156. let link=Yunqi.formatter.link;
  157. link.value = data;
  158. return link;
  159. }else{
  160. return '';
  161. }
  162. }},
  163. {field:"description",title:"简介",width: 300},
  164. {
  165. field:"local",
  166. title:"本地",
  167. width: 80,
  168. formatter: function (data){
  169. let tag=Yunqi.formatter.tag;
  170. if(data){
  171. tag.value='是';
  172. tag.type='success';
  173. }else{
  174. tag.value='否';
  175. tag.type='danger';
  176. }
  177. return tag;
  178. }
  179. },
  180. {
  181. field:"packed",
  182. title:"打包",
  183. width: 80,
  184. formatter:function (data,row){
  185. if(!row.local){
  186. return '';
  187. }
  188. let tag=Yunqi.formatter.tag;
  189. if(data){
  190. tag.value='是';
  191. tag.type='primary';
  192. }else{
  193. tag.value='否';
  194. tag.type='danger';
  195. }
  196. return tag;
  197. }
  198. },
  199. {
  200. field:"open",
  201. title:"开放",
  202. width: 80,
  203. formatter:function (data,row){
  204. if(!row.local){
  205. return '';
  206. }
  207. let sw=Yunqi.formatter.switch;
  208. sw.activeValue=1;
  209. sw.inactiveValue=0;
  210. sw.value=row.packed?data:0;
  211. sw.disabled=true;
  212. if(row.packed){
  213. sw.disabled=false;
  214. }
  215. return sw;
  216. }
  217. },
  218. {
  219. field: 'operate',
  220. title: __('操作'),
  221. direction:'column',
  222. width:100,
  223. action:{
  224. download:{
  225. text:__('下载'),
  226. type:'primary',
  227. tooltip:false,
  228. icon:'fa fa-download',
  229. method:'downloadAddon',
  230. visible:function (row) {
  231. return !row.download;
  232. }
  233. },
  234. install:{
  235. text:__('安装'),
  236. type:'primary',
  237. tooltip:false,
  238. icon:'fa fa-wrench',
  239. method:'installAddon',
  240. visible:function (row) {
  241. return row.download && !row.install;
  242. }
  243. },
  244. pack:{
  245. text:__('打包'),
  246. type:'primary',
  247. tooltip:false,
  248. icon:'fa fa-briefcase',
  249. method:'packAddon',
  250. visible:function (row) {
  251. return row.download && row.install && !row.packed;
  252. }
  253. },
  254. edit:{
  255. text:__('编辑'),
  256. type:'warning',
  257. tooltip:false,
  258. icon:'fa fa-edit',
  259. method:'editAddon',
  260. visible:function (row) {
  261. return row.local && row.is_author && !row.packed;
  262. }
  263. },
  264. uninstall:{
  265. text:__('卸载'),
  266. type:'danger',
  267. tooltip:false,
  268. icon:'fa fa-remove',
  269. method:'uninstallAddon',
  270. visible:function (row) {
  271. return row.install && row.packed;
  272. }
  273. },
  274. remove:{
  275. text:__('删除'),
  276. type:'danger',
  277. tooltip:false,
  278. icon:'fa fa-remove',
  279. method:'delAddon',
  280. visible:function (row) {
  281. return row.download && !row.install;
  282. }
  283. },
  284. },
  285. }
  286. ],
  287. buyDialog:{
  288. show:false,
  289. out_trade_no:'',
  290. transaction_id:'',
  291. expire_time:0,
  292. status:0,
  293. message:'',
  294. code_url:'',
  295. row:''
  296. }
  297. },
  298. onLoad:function (){
  299. setInterval(()=>{
  300. this.checkPayStatus();
  301. },2000)
  302. },
  303. methods:{
  304. changePlain:function (plain) {
  305. this.plain = plain;
  306. this.$refs.yuntable.submit();
  307. },
  308. packAddon:function(row) {
  309. Yunqi.ajax.post('addons/pack',row).then(res=>{
  310. this.$refs.yuntable.reload();
  311. });
  312. },
  313. editAddon:function (row){
  314. let that=this;
  315. Yunqi.api.open({
  316. title: __('修改本地扩展'),
  317. url: 'addons/create?id='+row.id,
  318. icon:'fa fa-edit',
  319. close:function (r) {
  320. if(r){
  321. that.$refs.yuntable.reload();
  322. }
  323. }
  324. });
  325. },
  326. downloadAddon:function(row){
  327. if(row.price>0){
  328. this.buyDialog.out_trade_no=create_out_trade_no();
  329. this.buyDialog.code_url=Yunqi.config.baseUrl+'addons/payCode?key='+row.key+'&out_trade_no='+this.buyDialog.out_trade_no;
  330. this.buyDialog.show=true;
  331. this.buyDialog.row=row;
  332. }else{
  333. Yunqi.ajax.post('addons/download', row).then(res=>{
  334. this.$refs.yuntable.reload();
  335. });
  336. }
  337. },
  338. payDownload:function (){
  339. let postdata={...this.buyDialog.row,transaction_id:this.buyDialog.transaction_id}
  340. Yunqi.ajax.post('addons/download',postdata).then(res=>{
  341. this.closeBuyDialog();
  342. this.$refs.yuntable.reload();
  343. });
  344. },
  345. checkPayStatus:function (){
  346. if(this.buyDialog.show){
  347. Yunqi.ajax.get('addons/checkPayStatus',{out_trade_no:this.buyDialog.out_trade_no,key:this.buyDialog.row.key}).then(res=>{
  348. if(res){
  349. this.buyDialog.transaction_id=res.transaction_id;
  350. this.buyDialog.expire_time=res.expire_time;
  351. this.buyDialog.message='支付成功';
  352. this.buyDialog.status=1;
  353. }
  354. });
  355. }
  356. },
  357. checkTransactionId:function (){
  358. let postdata={
  359. pack:this.buyDialog.row.pack,
  360. transaction_id:this.buyDialog.transaction_id
  361. };
  362. Yunqi.ajax.get('addons/checkTransactionId',postdata).then(res=>{
  363. this.buyDialog.status=res.status;
  364. this.buyDialog.expire_time=res.expire_time;
  365. if(res.status==0){
  366. this.buyDialog.message='交易单号不存在';
  367. }else{
  368. if(res.expire_time>0){
  369. this.buyDialog.message=formatTime(res.expire_time)+'过期';
  370. }else{
  371. this.buyDialog.message='交易单号已经过期';
  372. }
  373. }
  374. });
  375. },
  376. closeBuyDialog:function () {
  377. this.buyDialog={
  378. show:false,
  379. out_trade_no:'',
  380. transaction_id:'',
  381. expire_time:0,
  382. status:0,
  383. message:'',
  384. code_url:'',
  385. row:''
  386. }
  387. },
  388. installAddon:function(row)
  389. {
  390. Yunqi.ajax.post('addons/install',{key:row.key}).then(res=>{
  391. this.$refs.yuntable.reload();
  392. });
  393. },
  394. uninstallAddon:function(row)
  395. {
  396. let that=this;
  397. Yunqi.api.open({
  398. title: __('卸载扩展'),
  399. url: 'addons/uninstall?key='+row.key,
  400. icon:'fa fa-remove',
  401. close:function (r) {
  402. if(r){
  403. that.$refs.yuntable.reload();
  404. }
  405. }
  406. });
  407. },
  408. delAddon:function (row){
  409. let that=this;
  410. Yunqi.confirm('删除扩展将会清空掉所有文件,重新下载扩展可能会再次收取费用,你确定要删除吗?','提醒').then(res=>{
  411. Yunqi.ajax.post('addons/del',{key:row.key}).then(res=>{
  412. that.$refs.yuntable.reload();
  413. });
  414. });
  415. },
  416. createAddon:function(){
  417. let that=this;
  418. Yunqi.api.open({
  419. title: __('创建本地扩展'),
  420. url: 'addons/create',
  421. icon:'fa fa-plus',
  422. close:function (r) {
  423. if(r){
  424. that.$refs.yuntable.reload();
  425. }
  426. }
  427. });
  428. }
  429. }
  430. }
  431. </script>
  432. <style>
  433. .install:hover{
  434. background:var(--el-color-primary-light-9);
  435. border:1px solid var(--el-color-primary-light-5);
  436. }
  437. .paycode{
  438. text-align:center;
  439. }
  440. .message{
  441. margin-top:5px;
  442. }
  443. .footer{
  444. margin-top:15px;
  445. }
  446. </style>