Compare commits
387 Commits
dependabot
...
master
Author | SHA1 | Date |
---|---|---|
isummer | e12779d654 | 2 years ago |
isummer | ac590563a7 | 2 years ago |
isummer | 8fc1d353c9 | 2 years ago |
isummer | 35b64d74de | 2 years ago |
isummer | a064988f56 | 2 years ago |
isummer | adff361c11 | 2 years ago |
isummer | 419e39eaaa | 2 years ago |
isummer | 9d9cb3f2cb | 2 years ago |
isummer | dd802dccbb | 2 years ago |
isummer | 1262bff671 | 2 years ago |
isummer | 289737ed00 | 2 years ago |
isummer | dc7b491534 | 2 years ago |
isummer | eed0f5194c | 2 years ago |
isummer | e0599585be | 2 years ago |
isummer | 42451f2cb0 | 2 years ago |
isummer | 646162593e | 2 years ago |
isummer | 200494fcf3 | 2 years ago |
isummer | fe5a7605f0 | 2 years ago |
isummer | f70351d8e5 | 2 years ago |
isummer | 9e2f40383a | 2 years ago |
isummer | debe95791e | 2 years ago |
isummer | a3887825c9 | 2 years ago |
isummer | 8a8f9ef7fe | 2 years ago |
isummer | 8e325e6cde | 2 years ago |
isummer | 92961cfa61 | 2 years ago |
isummer | 8c25aab63c | 2 years ago |
isummer | 0cc5084390 | 2 years ago |
isummer | 4d98981485 | 2 years ago |
isummer | a7a1472533 | 2 years ago |
isummer | 332d12bddf | 2 years ago |
isummer | 6439824468 | 2 years ago |
isummer | 42478f21d9 | 2 years ago |
isummer | 2c67305f8a | 2 years ago |
isummer | 79037d5248 | 2 years ago |
isummer | 525ec097d7 | 2 years ago |
isummer | a35ca0b087 | 2 years ago |
isummer | d9ac93ccc1 | 2 years ago |
isummer | 1ff3da6896 | 2 years ago |
isummer | cbad06e95d | 2 years ago |
isummer | b093d7133b | 2 years ago |
isummer | 7aa0471ba9 | 2 years ago |
isummer | 2224ce27c7 | 2 years ago |
isummer | d8b124c1a7 | 2 years ago |
isummer | d1a5d69ac8 | 2 years ago |
isummer | 8a8d2f2400 | 2 years ago |
isummer | 49832ca702 | 2 years ago |
isummer | 7075bc7ed6 | 2 years ago |
MMXX | 7d70f381a1 | 2 years ago |
MMXX | 15a506450c | 2 years ago |
isummer | 93c13fa776 | 2 years ago |
MMXX | c8f02465d0 | 2 years ago |
isummer | 2e240735dc | 2 years ago |
I夏 | ec908f0dea | 3 years ago |
I夏 | 47abaf61f5 | 3 years ago |
I夏 | 31fe8664a9 | 3 years ago |
nineven | f4ca8d48f9 | 3 years ago |
nineven | e2b9b12613 | 3 years ago |
nineven | f772d65765 | 3 years ago |
nineven | 3ad5e03504 | 3 years ago |
nineven | 5f967a9b52 | 3 years ago |
nineven | e7858a840e | 3 years ago |
nineven | b191cbae6b | 3 years ago |
nineven | c36ab08f35 | 3 years ago |
nineven | a5b73c3695 | 3 years ago |
nineven | 0c6b61327a | 3 years ago |
nineven | 92c0345341 | 3 years ago |
nineven | 25c2ea4c7a | 3 years ago |
nineven | dfcf213bed | 3 years ago |
nineven | 2b29e0e3bd | 3 years ago |
nineven | a9bbdd40bd | 3 years ago |
nineven | 97349e758f | 3 years ago |
nineven | 156bf67c1c | 3 years ago |
nineven | 1d75c8ed23 | 3 years ago |
nineven | ef243feb9f | 3 years ago |
nineven | 58472fb9e4 | 3 years ago |
nineven | 6c25f6a932 | 3 years ago |
nineven | 2d21ee9150 | 3 years ago |
nineven | 04ba947219 | 3 years ago |
nineven | 884d6a47e8 | 3 years ago |
nineven | 0a64689902 | 3 years ago |
nineven | 5ca5b0eb34 | 3 years ago |
nineven | 3bbabdafdb | 3 years ago |
nineven | 4cd0dc7586 | 3 years ago |
nineven | 5eb947843e | 3 years ago |
nineven | 17ab6e6efd | 3 years ago |
nineven | 94bc5cc1db | 3 years ago |
nineven | 584f50ba20 | 3 years ago |
nineven | df38944eab | 3 years ago |
nineven | fe880b27b7 | 3 years ago |
nineven | 8316a52595 | 3 years ago |
nineven | 747d2b3dfa | 3 years ago |
nineven | 04ae8cccc4 | 3 years ago |
nineven | 3b8134aafd | 3 years ago |
nineven | bb9bdf8891 | 3 years ago |
nineven | bc0cee937d | 3 years ago |
nineven | d1a41a179b | 3 years ago |
nineven | 3ff322849a | 3 years ago |
nineven | 4184f2ad1c | 3 years ago |
nineven | 22a9b8d816 | 3 years ago |
nineven | 2390397f1b | 3 years ago |
nineven | ae9dfae6a3 | 3 years ago |
nineven | d7e3186f9d | 3 years ago |
nineven | 2bfd694f23 | 3 years ago |
nineven | 63e09c1925 | 3 years ago |
nineven | 391e4987de | 3 years ago |
nineven | 88745550d4 | 3 years ago |
nineven | 59e73fa83e | 3 years ago |
nineven | 5eca01278b | 3 years ago |
nineven | 5edf7cd65a | 3 years ago |
nineven | cf9d9eeaf8 | 3 years ago |
nineven | c4a4db2c7e | 3 years ago |
nineven | 24a8307164 | 3 years ago |
nineven | 05669b8d3e | 3 years ago |
nineven | 32c3058d57 | 3 years ago |
nineven | 4bbae93933 | 3 years ago |
nineven | f94184551a | 3 years ago |
nineven | dd73441bdd | 3 years ago |
nineven | 4e7927a332 | 3 years ago |
MMXX | fc1963c8a9 | 3 years ago |
MMXX | d15b583804 | 3 years ago |
MMXX | d930603919 | 3 years ago |
MMXX | 9b9be3fcf9 | 3 years ago |
MMXX | 378912944f | 3 years ago |
MMXX | 75c7d365a3 | 3 years ago |
MMXX | 1dec3b7de2 | 3 years ago |
MMXX | eeba5b409a | 3 years ago |
nineven | 684a407f97 | 3 years ago |
nineven | 5901d63f3e | 3 years ago |
MMXX | cf14dcb0a5 | 3 years ago |
MMXX | e780a2597e | 3 years ago |
MMXX | 02f908e3de | 3 years ago |
MMXX | 7ceb9c83c1 | 3 years ago |
MMXX | 77d97fd1d2 | 3 years ago |
nineven | 98fe1d5f61 | 3 years ago |
nineven | fb77c251c3 | 3 years ago |
nineven | c765658fb5 | 3 years ago |
nineven | dd1fb29ba0 | 3 years ago |
nineven | d571b399d7 | 3 years ago |
nineven | 115d1c95df | 3 years ago |
nineven | e54f6c1286 | 3 years ago |
nineven | 75fecbca10 | 3 years ago |
nineven | 96295132d9 | 3 years ago |
nineven | ec327598a2 | 3 years ago |
nineven | 81db86b9ef | 3 years ago |
nineven | 6076659bf1 | 3 years ago |
nineven | 4b90ce682b | 3 years ago |
nineven | f00135a6a4 | 3 years ago |
nineven | 8ce3b14475 | 3 years ago |
nineven | 25d09e8cf1 | 3 years ago |
nineven | c6e78a6eab | 3 years ago |
nineven | e9c6cadeb6 | 3 years ago |
nineven | 153f800b91 | 3 years ago |
nineven | 5e380fa09e | 3 years ago |
nineven | 42bab0739b | 3 years ago |
nineven | 518fc3101e | 3 years ago |
nineven | 875a3a4305 | 3 years ago |
nineven | 6051f443c1 | 3 years ago |
nineven | c4fd9aa793 | 3 years ago |
nineven | 9ba02e449d | 3 years ago |
nineven | cb841b5cf7 | 3 years ago |
nineven | 9353abc8a9 | 3 years ago |
nineven | 06bace9f66 | 3 years ago |
nineven | ce31dd5621 | 3 years ago |
nineven | 91e042ea1d | 3 years ago |
nineven | f02eb026de | 3 years ago |
nineven | 44cfd03cee | 3 years ago |
nineven | 14f60d4f8d | 3 years ago |
nineven | 614db12422 | 3 years ago |
nineven | 10ab90a104 | 3 years ago |
nineven | f5ffc3632f | 3 years ago |
nineven | adc71de160 | 3 years ago |
nineven | 6f959fa4a9 | 3 years ago |
nineven | 3d2ce3b73d | 3 years ago |
nineven | 192d4cadc0 | 3 years ago |
nineven | 9f2fea094d | 3 years ago |
nineven | 32bdc4ba9e | 3 years ago |
nineven | fdd0abb07e | 3 years ago |
nineven | a580dddd83 | 3 years ago |
nineven | 2f32b71b2b | 3 years ago |
MMXX | 03a6202ee2 | 3 years ago |
MMXX | 7e15211fd2 | 3 years ago |
MMXX | ae58a71ee4 | 3 years ago |
MMXX | b270d8e5c6 | 3 years ago |
MMXX | 32ca967d07 | 3 years ago |
MMXX | 878183dbce | 3 years ago |
MMXX | bebc8417eb | 3 years ago |
MMXX | de511bf90c | 3 years ago |
MMXX | a8c1df58ee | 3 years ago |
MMXX | ef335e118a | 3 years ago |
MMXX | 03f66df7b9 | 3 years ago |
MMXX | 4d4ee64a65 | 3 years ago |
MMXX | 04ccfe77a3 | 3 years ago |
MMXX | d085d86a26 | 3 years ago |
MMXX | 8a60be6f4f | 3 years ago |
MMXX | 869d5ee7bb | 3 years ago |
MMXX | 9572382a9e | 3 years ago |
MMXX | 7ad5bc8161 | 3 years ago |
MMXX | 59d7d905d3 | 3 years ago |
MMXX | c361d740bf | 3 years ago |
MMXX | 17c1f0612a | 3 years ago |
MMXX | 2b5325ff32 | 3 years ago |
MMXX | 09257733f8 | 3 years ago |
MMXX | 5dd1dd0681 | 3 years ago |
MMXX | 979b6f0386 | 3 years ago |
MMXX | e8e6ea962a | 3 years ago |
MMXX | c50005e7c7 | 3 years ago |
MMXX | 465aea9744 | 3 years ago |
MMXX | 7c2a29b86d | 3 years ago |
MMXX | f8418f6414 | 3 years ago |
youngS | def6c9dfc8 | 3 years ago |
youngS | 205505cb0e | 3 years ago |
youngS | 106ae636a2 | 3 years ago |
youngS | 2e96183c06 | 3 years ago |
youngS | 216bc367c4 | 3 years ago |
youngS | e559267de3 | 3 years ago |
youngS | f04c4411c7 | 3 years ago |
youngS | a60a7d6011 | 3 years ago |
youngS | d3fc7327a6 | 3 years ago |
youngS | 4decc14bf8 | 3 years ago |
nineven | d657c709f6 | 3 years ago |
nineven | 73d783b97d | 3 years ago |
nineven | b18dfa7a14 | 3 years ago |
youngS | 0d26e5ac7b | 3 years ago |
youngS | bda9cf994d | 3 years ago |
youngS | 9d0d36ca63 | 3 years ago |
youngS | 26e6efeaf4 | 3 years ago |
youngS | 49c35275b6 | 3 years ago |
youngS | 92ba4fc258 | 3 years ago |
youngS | c8a69acb84 | 3 years ago |
youngS | 7932dde3b4 | 3 years ago |
youngS | 55f5f65e15 | 3 years ago |
youngS | fd43dcfea4 | 3 years ago |
youngS | 4c41efa46f | 3 years ago |
youngS | d3e0c53b8f | 3 years ago |
youngS | bd77da66b7 | 3 years ago |
youngS | ebed9b1aa4 | 3 years ago |
youngS | 0c5c4a6ce7 | 3 years ago |
youngS | b3899d4a97 | 3 years ago |
youngS | 27b8a21556 | 3 years ago |
youngS | bbf9664fc7 | 3 years ago |
youngS | 86467ef2fd | 3 years ago |
youngS | 2aedb458ee | 3 years ago |
youngS | 2e491db16c | 3 years ago |
youngS | 8a59b8d329 | 3 years ago |
youngS | fce8a09d5e | 3 years ago |
fxC | 29328d293b | 3 years ago |
fxC | 2ec7fb05eb | 3 years ago |
youngS | 341cf21367 | 3 years ago |
youngS | 6412e36d0b | 3 years ago |
youngS | 8bf925e9df | 3 years ago |
youngS | d550d20998 | 3 years ago |
youngS | c170086609 | 3 years ago |
youngS | bd8c8d00cc | 3 years ago |
youngS | a2c5d1bd3f | 3 years ago |
youngS | 169347ca16 | 3 years ago |
youngS | 372455bcb3 | 3 years ago |
youngS | d943b5527d | 3 years ago |
youngS | 5316ed83c1 | 3 years ago |
youngS | c173262a0b | 3 years ago |
fxC | 5be7115e91 | 3 years ago |
youngS | f30aafb5d9 | 3 years ago |
fxC | 34971b792a | 3 years ago |
youngS | f49c067015 | 3 years ago |
youngS | 002c90d5e3 | 3 years ago |
youngS | 4c29d32d67 | 3 years ago |
youngS | 819c9a7017 | 3 years ago |
youngS | 479abff102 | 3 years ago |
youngS | 20ac8eadda | 3 years ago |
youngS | 1cc05645ec | 3 years ago |
youngS | 2ee4352544 | 3 years ago |
youngS | 7702fa5209 | 3 years ago |
youngS | 50da6044a4 | 3 years ago |
youngS | 7d781de388 | 3 years ago |
youngS | ab52639caf | 3 years ago |
youngS | 5232ba5fe6 | 3 years ago |
youngS | 47861511fc | 3 years ago |
fxC | 0a20226dd7 | 3 years ago |
fxC | cb4fc0b827 | 3 years ago |
youngS | 674bf66827 | 3 years ago |
fxC | abd2db398d | 3 years ago |
youngS | 9d3b5c582e | 3 years ago |
youngS | abbe709d27 | 3 years ago |
fxC | b3637c6844 | 3 years ago |
youngS | 9b7590146a | 3 years ago |
youngS | 7309eaf9b5 | 3 years ago |
youngS | edd603b8e9 | 3 years ago |
youngS | 9b69021337 | 3 years ago |
youngS | e7d4df5941 | 3 years ago |
youngS | b772d2921e | 3 years ago |
youngS | dd5d0ed0ed | 3 years ago |
youngS | dc2fa091cb | 3 years ago |
youngS | d34073301b | 3 years ago |
youngS | fac7eccc05 | 3 years ago |
youngS | 4533e04850 | 3 years ago |
youngS | 0e2578738f | 3 years ago |
youngS | 08c6b7b87f | 3 years ago |
youngS | 7c5ab20dd9 | 3 years ago |
youngS | 1a9cae8cb7 | 3 years ago |
youngS | e34ca43cfc | 3 years ago |
youngS | 75d5a5df76 | 3 years ago |
youngS | ac8614b54c | 3 years ago |
youngS | 1e1385da84 | 3 years ago |
youngS | 0bac3e55f4 | 3 years ago |
youngS | 820e1df84e | 3 years ago |
youngS | 08ffa72eab | 3 years ago |
youngS | 6861c65b83 | 3 years ago |
youngS | 439db9788a | 3 years ago |
youngS | 2feda8800c | 3 years ago |
youngS | b10a40d177 | 3 years ago |
youngS | 3325814c03 | 3 years ago |
youngS | f6918011ca | 3 years ago |
youngS | d7a31c62b3 | 3 years ago |
youngS | d154381895 | 3 years ago |
youngS | 13a67be0ff | 3 years ago |
youngS | b815950f7d | 3 years ago |
youngS | 4316398d82 | 3 years ago |
youngS | 749d72b513 | 3 years ago |
youngS | bfb3738d69 | 3 years ago |
youngS | 3c80635d5f | 3 years ago |
youngS | ed05083bbe | 3 years ago |
youngS | 31677fb1fd | 3 years ago |
youngS | cf1267deb2 | 3 years ago |
youngS | 5988e0e1a9 | 3 years ago |
youngS | 81f1f75fb1 | 3 years ago |
youngS | 08e7eb3476 | 3 years ago |
youngS | 0148905071 | 3 years ago |
youngS | bab6e083bf | 3 years ago |
youngS | adaf7af866 | 3 years ago |
youngS | e8931df00f | 3 years ago |
youngS | 1dc6e84ba7 | 3 years ago |
youngS | cac1703957 | 3 years ago |
youngS | dfcf878416 | 3 years ago |
youngS | 45978aae73 | 3 years ago |
youngS | e84f47170a | 3 years ago |
youngS | 69c699aebb | 3 years ago |
youngS | 19709c7da3 | 3 years ago |
youngS | dc8de286c5 | 3 years ago |
youngS | 9b8412304f | 3 years ago |
youngS | d6ce64c3b6 | 3 years ago |
youngS | 4f0c8a302c | 3 years ago |
youngS | 3ade1efadb | 3 years ago |
youngS | 90dceee1c5 | 3 years ago |
youngS | d460da0024 | 3 years ago |
youngS | 10297e1616 | 3 years ago |
youngS | 37df9f4a5d | 3 years ago |
youngS | a8e8402eff | 3 years ago |
youngS | dd218fe745 | 3 years ago |
youngS | 42cb1bfc88 | 3 years ago |
youngS | d8b02a74ab | 3 years ago |
youngS | 7599e5f3a2 | 3 years ago |
youngS | 4501b5dc2a | 3 years ago |
youngS | 58e7f8fa6a | 3 years ago |
youngS | 436e26af37 | 3 years ago |
youngS | cb3738f4de | 3 years ago |
youngS | aa83de23b5 | 3 years ago |
youngS | 5169c8a477 | 3 years ago |
youngS | 83509a79de | 3 years ago |
youngS | 9abdc5f5ae | 3 years ago |
youngS | a95a2fb22f | 3 years ago |
youngS | 1bd0f08a4b | 3 years ago |
youngS | cdf778d3f3 | 3 years ago |
youngS | bb5d5829df | 3 years ago |
youngS | a5a79867f1 | 3 years ago |
youngS | 8c1ca01532 | 3 years ago |
youngS | 4e3af4de35 | 3 years ago |
youngS | 586136729a | 3 years ago |
youngS | 3c4e5aa6e3 | 3 years ago |
youngS | cad1a77f8f | 3 years ago |
youngS | f7f0896893 | 3 years ago |
youngS | f3349ecc5b | 3 years ago |
youngS | 7fba632390 | 3 years ago |
youngS | aa33e5640b | 3 years ago |
youngS | 45d813cca3 | 3 years ago |
youngS | 95b4b45da8 | 3 years ago |
youngS | 00032239b0 | 3 years ago |
youngS | 86d5623437 | 3 years ago |
youngS | d4e4e9b278 | 3 years ago |
youngS | a6f0cb0174 | 3 years ago |
youngS | b40f93a16c | 3 years ago |
youngS | e6f8b2f628 | 3 years ago |
youngS | ed841bc8fb | 4 years ago |
youngS | a59958e1af | 4 years ago |
youngS | 5835b4d6e1 | 4 years ago |
youngS | 5bac330551 | 4 years ago |
youngS | 1cc239698b | 4 years ago |
youngS | 56cd35565f | 4 years ago |
youngS | 30db4882b4 | 4 years ago |
@ -1,144 +1,63 @@ |
||||
##### 从git上面下载源码 |
||||
``` |
||||
cd /data/ |
||||
git clone https://github.com/nineaiyu/FlyApps |
||||
``` |
||||
|
||||
#### 超级签名依赖部署 |
||||
##### fastlane [相关文档](https://github.com/fastlane/fastlane/blob/master/spaceship/docs/DeveloperPortal.md) |
||||
``` |
||||
# fastlane |
||||
#1 gem ruby安装 |
||||
yum install gem -y |
||||
yum install ruby-devel -y |
||||
yum install gcc gcc-c++ -y |
||||
|
||||
#gem修改为国内镜像 |
||||
gem sources --add https://gems.ruby-china.com/ --remove https://rubygems.org/ |
||||
|
||||
gem sources -l |
||||
#https://gems.ruby-china.com |
||||
#确保只有 gems.ruby-china.com |
||||
|
||||
#2 更新rubby |
||||
gpg2 --keyserver hkp://pool.sks-keyservers.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB |
||||
|
||||
#如果脚本执行失败,可以这样 |
||||
# echo 199.232.68.133 raw.githubusercontent.com >> /etc/hosts |
||||
|
||||
curl -L get.rvm.io | bash -s stable |
||||
source /etc/profile.d/rvm.sh |
||||
rvm list known |
||||
rvm install 2.7 |
||||
|
||||
#3 安装fastlane |
||||
gem install fastlane |
||||
gem install pry |
||||
|
||||
# space 好像有点问题,需要把这个注释掉 |
||||
vim /usr/local/rvm/gems/ruby-2.7.0/gems/fastlane-2.146.1/spaceship/lib/spaceship/base.rb +298 |
||||
#v.gsub!("\n", "\n\t") # to align nested elements #注释掉,要不然会报错 |
||||
|
||||
``` |
||||
##### isign |
||||
``` |
||||
# python2.7 |
||||
yum update python -y |
||||
pip install -U setuptools pip |
||||
|
||||
wget https://github.com/nineaiyu/isign/archive/v1.8.0.tar.gz |
||||
tar xvf v1.8.0.tar.gz |
||||
cd isign-1.8.0/ |
||||
|
||||
python setup.py build |
||||
python setup.py install |
||||
``` |
||||
|
||||
### FlyApp 服务器搭建 [python3 环境] |
||||
|
||||
|
||||
##### 搭建python env 环境 |
||||
``` |
||||
yum install python36 python36-devel redis mariadb-server mariadb-devel -y |
||||
python3 -m venv py3 |
||||
source py3/bin/activate |
||||
``` |
||||
|
||||
###### 安装pip包 |
||||
``` |
||||
cd FlyApps/fir_ser/ |
||||
pip install -r requirements.txt |
||||
``` |
||||
|
||||
###### 配置数据库 |
||||
``` |
||||
在 settings.py 配置redis 和 mysql 数据库 |
||||
``` |
||||
|
||||
###### 迁移数据库 |
||||
``` |
||||
#如果是mysql,需要做一下配置,如果是sqlite,需要升级sqlite |
||||
#记得根据配置创建数据库 |
||||
#create database flyapp default character set utf8 COLLATE utf8_general_ci; |
||||
#grant all on flyapp.* to flyuser@'127.0.0.1' identified by 'flypwd00oo.1'; |
||||
|
||||
python manage.py makemigrations |
||||
python manage.py migrate |
||||
``` |
||||
|
||||
### FlyApp web端搭建 |
||||
###### npm编译环境 |
||||
``` |
||||
yum install npm |
||||
npm install -g n |
||||
n latest |
||||
npm install -g yarn |
||||
``` |
||||
|
||||
###### 编译web端 |
||||
``` |
||||
cd FlyApps/fir_client/ |
||||
vim src/restful/index.js #修改api接口地址 |
||||
|
||||
yarn install |
||||
yarn build |
||||
``` |
||||
|
||||
|
||||
###### 编译下载页面 |
||||
``` |
||||
cd FlyApps/fir_download/ |
||||
vim src/restful/download.js #修改api接口地址 |
||||
|
||||
yarn install |
||||
yarn build |
||||
``` |
||||
|
||||
###### web目录操作 |
||||
``` |
||||
# web目录: /www/wwwroot/fly.dvcloud.xin/ |
||||
|
||||
cd /www/wwwroot/fly.dvcloud.xin/ |
||||
cp -a /data/FlyApps/fir_client/dist/* . |
||||
cp -a /data/FlyApps/fir_download/dist/* . |
||||
``` |
||||
|
||||
##### 更新sqllite |
||||
``` |
||||
tar xvf sqlite-autoconf-3310100.tar.gz |
||||
cd sqlite-autoconf-3310100 |
||||
|
||||
./configure --prefix=/usr/local/sqlite |
||||
make -j4 |
||||
|
||||
make install |
||||
rm -rf /usr/bin/sqlite3 |
||||
|
||||
ln -s /usr/local/sqlite/bin/sqlite3 /usr/bin/sqlite3 |
||||
ll /usr/bin/sqlite3 |
||||
|
||||
|
||||
echo "/usr/local/sqlite/lib" > /etc/ld.so.conf.d/sqlite3.conf |
||||
ldconfig |
||||
|
||||
``` |
||||
### 用与应用分发,苹果超级签名 |
||||
#### 部署前准备 |
||||
- 备案域名【至少需要一个域名,以下可通过子域名部署】 |
||||
- API域名 |
||||
- 前端web域名 |
||||
- 下载页域名 |
||||
- 下载页域名可配置多个 |
||||
- 存储域名(使用阿里云oss存储) |
||||
- ssl证书 |
||||
- API域名证书 |
||||
- 存储域名证书(使用阿里云oss存储) |
||||
- 前端web域名证书(可选) |
||||
- Centos8Stream 服务器 |
||||
- 如果使用oss存储,则带宽为1M,若使用本地存储,则带宽越大越好 |
||||
- 如果使用超级签,最低配置为2cpu 4G内存,若干不使用签名,则1cpu2G就行 |
||||
- 阿里云短信或极光短信服务【可选一个,主要用与注册,重置密码】 |
||||
- 阿里云短信 |
||||
- 极光短信 |
||||
- 邮箱服务【可选,用与注册,重置密码,通知信息】 |
||||
- 阿里云OSS存储【可选】 |
||||
- [sts授权配置](https://help.aliyun.com/document_detail/100624.html) |
||||
- 阿里云CDN【可选,用与加速访问】 |
||||
- 极验验证【可选,滑动验证服务】 |
||||
- 微信公众号【可选,用与微信扫描登录】 |
||||
- 阿里云支付【可选,用与购买下载次数】 |
||||
- 微信支付【可选,用与购买下载次数】 |
||||
|
||||
#### 自用搭建建议 |
||||
- 阿里云服务器需要1cpu 2G内存,无需系统盘,如果使用超级签,可以适当增加配置 |
||||
- 需要阿里云OSS存储和阿里云CDN,并且OSS存储和阿里云服务器部署同一个地区 |
||||
- 可以申请一个极验进行滑动验证,或者开启验证码验证 |
||||
- 阿里云备案域名:api和前端可以使用一个域名,下载页单独域名 |
||||
|
||||
#### 部署必备资料 |
||||
- 域名证书 |
||||
- web域名和证书 |
||||
- api域名和证书 |
||||
- 下载页域名(可配置证书) |
||||
- 存储域名和证书 |
||||
- 本地存储,则该域名和证书可以和api域名证书一致 |
||||
- 阿里云oss存储 |
||||
- 开启cdn,需要新域名和证书 |
||||
- 不开启,无需域名和证书 |
||||
- Centos8Stream 服务器 |
||||
|
||||
## 部署方式 |
||||
|
||||
### 1.[Docker 部署](./doc/docker.md) 【推荐】 |
||||
|
||||
### 2.[本地部署](./doc/local.md) |
||||
|
||||
### 功能预览 |
||||
![img_1.png](./doc/images/img_1.png) |
||||
![img_2.png](./doc/images/img_2.png) |
||||
![img_3.png](./doc/images/img_3.png) |
||||
![img_4.png](./doc/images/img_4.png) |
||||
![img_5.png](./doc/images/img_5.png) |
||||
![img_6.png](./doc/images/img_6.png) |
||||
![img_7.png](./doc/images/img_7.png) |
||||
![img_8.png](./doc/images/img_8.png) |
||||
![img_9.png](./doc/images/img_9.png) |
||||
![img_10.png](./doc/images/img_10.png) |
||||
![img_11.png](./doc/images/img_11.png) |
@ -0,0 +1,102 @@ |
||||
### Docker最小化部署前准备,如果使用超级签和云存储,需要使用阿里云的服务器 |
||||
系统|Centos 8 Stream 纯净系统 [2cpu 4G内存] |
||||
----|---- |
||||
域名|```app.hehelucky.cn``` |
||||
域名SSL证书| nginx 格式证书 [阿里云和腾讯云都可以申请免费ssl证书] |
||||
数据路径| ```/data``` |
||||
|
||||
|
||||
### 开始部署 |
||||
##### 1.从git上面下载源码 |
||||
``` |
||||
cd /data/ |
||||
dnf install git -y |
||||
git clone https://github.com/nineaiyu/flyapps |
||||
``` |
||||
|
||||
## 注意,下面展示的相对路径,都是以```/data/flyapps```为相对目录 |
||||
|
||||
#### 2.docker环境安装 |
||||
``` |
||||
cd /data/flyapps/docker/init |
||||
sh init.sh |
||||
``` |
||||
|
||||
#### 3.配置域名和证书,如果有cdn或者oss,也要进行配置 |
||||
a.将域名证书通过```sftp软件```或者```rz命令```复制到```/data/flyapps/nginx.conf.d```目录中 |
||||
|
||||
b.将域名证书分别重命名为 ```域名.pem``` 和 ```域名.key``` .本次使用的域名是 ```app.hehelucky.cn``` ,因此,证书名称类似如下 |
||||
```shell script |
||||
nginx.conf.d/app.hehelucky.cn.key |
||||
nginx.conf.d/app.hehelucky.cn.pem |
||||
``` |
||||
c.修改NGINX配置文件```nginx.conf.d/flyapps-vhost.conf```,将```server_name```字段修改为域名,将```ssl_certificate```和 |
||||
```ssl_certificate_key```修改为对应证书路径,修改之后,对应字段如下 |
||||
```shell |
||||
server_name app.hehelucky.cn; |
||||
ssl_certificate /etc/nginx/conf.d/app.hehelucky.cn.pem; |
||||
ssl_certificate_key /etc/nginx/conf.d/app.hehelucky.cn.key; |
||||
``` |
||||
|
||||
#### 4.配置api服务需要修改api和web域名,如果有需求,还可以配置 短信,邮箱,geetest,存储等信息 |
||||
##### fir_ser配置文件 ```fir_ser/config.py``` |
||||
```python |
||||
class DOMAINCONF(object): |
||||
API_DOMAIN = "https://app.hehelucky.cn" # 用与开启本地存储,上传应用配置 |
||||
WEB_DOMAIN = "https://app.hehelucky.cn" # 用于超级签跳转配置,该域名一般为前端页面域名 |
||||
``` |
||||
|
||||
##### fir_client配置文件 ```fir_client/vue.confjg.js``` |
||||
```javascript |
||||
const pro_base_env = { |
||||
baseUrl: '/', //该选项可以填写web-api的域名,类似 https://api.xxx.com/ |
||||
index_static: '/', //若配置cdn等加速,可以填写cdn加速域名 |
||||
baseShortUrl: '/', //该选项可以填写short-api的域名,也可以和web-api域名一样,类似 https://api.xxx.com/ |
||||
short_static: '/short/', //若配置cdn等加速,可以填写cdn加速域名 |
||||
version: version, |
||||
}; |
||||
``` |
||||
|
||||
##### 构建静态资源 |
||||
``` |
||||
cd /data/flyapps/docker/scripts |
||||
sh build.sh |
||||
``` |
||||
|
||||
##### 启动所有服务 |
||||
``` |
||||
cd /data/flyapps/docker/scripts |
||||
sh start_all.sh |
||||
``` |
||||
|
||||
##### 关闭所有服务 |
||||
``` |
||||
cd /data/flyapps/docker/scripts |
||||
sh stop_all.sh |
||||
``` |
||||
|
||||
##### 根据提示创建默认管理用户,用与访问管理后台 |
||||
```shell |
||||
docker exec -it flyapps python manage.py createsuperuser |
||||
``` |
||||
|
||||
##### 测试访问 |
||||
- 在浏览器输入自己配置的域名 https://app.hehelucky.cn/ 进行访问 |
||||
- 管理后台访问 https://app.hehelucky.cn:3448/ 进行访问 |
||||
|
||||
|
||||
##### 如果要使用本地的数据库和redis,api服务使用容器,需要修改文件```/data/flyapps/docker/flyapps/docker-compose.yml``` |
||||
```shell |
||||
external_links: |
||||
- mariadb:mariadb |
||||
- redis:redis |
||||
``` |
||||
修改为 |
||||
```shell |
||||
extra_hosts: |
||||
- "mariadb:172.31.31.1" |
||||
- "redis:172.31.31.1" |
||||
``` |
||||
并将```nginx:```下面的配置注释掉 |
||||
|
||||
同时还需要修改mariadb和redis授权 |
After Width: | Height: | Size: 77 KiB |
After Width: | Height: | Size: 77 KiB |
After Width: | Height: | Size: 53 KiB |
After Width: | Height: | Size: 54 KiB |
After Width: | Height: | Size: 51 KiB |
After Width: | Height: | Size: 52 KiB |
After Width: | Height: | Size: 29 KiB |
After Width: | Height: | Size: 70 KiB |
After Width: | Height: | Size: 44 KiB |
After Width: | Height: | Size: 57 KiB |
After Width: | Height: | Size: 56 KiB |
@ -0,0 +1,166 @@ |
||||
### 本地部署前准备 |
||||
系统 | Centos 8 Stream [2cpu 4G内存] |
||||
----|---- |
||||
域名|```app.hehelucky.cn``` |
||||
域名SSL证书| nginx 格式证书 [阿里云和腾讯云都可以申请免费ssl证书] |
||||
数据路径| ```/data``` |
||||
|
||||
|
||||
##### 从git上面下载源码 |
||||
```shell |
||||
cd /data/ |
||||
dnf install git gcc zip unzip -y |
||||
git clone https://github.com/nineaiyu/flyapps |
||||
``` |
||||
|
||||
|
||||
### flyapps 本地部署 [python3 环境] |
||||
|
||||
##### 搭建python env 环境 |
||||
```shell |
||||
dnf install python39 python39-devel redis mariadb-server mariadb-devel -y |
||||
python3.9 -m venv py39 |
||||
source py39/bin/activate |
||||
``` |
||||
|
||||
###### 安装pip包 |
||||
```shell |
||||
cd /data/flyapps/fir_ser/ |
||||
pip install -U setuptools pip -i https://pypi.tuna.tsinghua.edu.cn/simple/ |
||||
pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple/ |
||||
``` |
||||
|
||||
#### 配置数据库 |
||||
##### 启动mariadb数据库 |
||||
```shell |
||||
systemctl restart mariadb |
||||
systemctl enable mariadb |
||||
``` |
||||
##### 创建mysql数据库 |
||||
```shell |
||||
mysql |
||||
``` |
||||
执行下面mysql命令 |
||||
```mariadb |
||||
create database flyapps default character set utf8 COLLATE utf8_general_ci; |
||||
grant all on flyapps.* to flyuser@'127.0.0.1' identified by 'KGzKjZpWBp4R4RSa'; |
||||
``` |
||||
##### 启动redis数据库 |
||||
```shell |
||||
echo 'requirepass nineven' >> /etc/redis.conf # 配置授权密码 |
||||
systemctl restart redis |
||||
systemctl enable redis |
||||
``` |
||||
|
||||
### flyapps zsign ipa重签名工具安装 |
||||
```shell |
||||
dnf install openssl-devel -y |
||||
dnf install gcc-c++ gcc -y |
||||
cd /data/flyapps/fir_ser/ |
||||
tar xvf zsign-1.1.2.tar.gz |
||||
cd zsign-1.1.2/ |
||||
g++ *.cpp common/*.cpp -lcrypto -O3 -std=c++11 -o /usr/bin/zsign |
||||
``` |
||||
|
||||
|
||||
#### 配置api服务需要修改api和web域名,如果有需求,还可以配置 短信,邮箱,geetest,存储等信息 |
||||
##### fir_ser配置文件 ```fir_ser/config.py``` |
||||
```python |
||||
class DOMAINCONF(object): |
||||
API_DOMAIN = "https://app.hehelucky.cn" # 用与开启本地存储,上传应用配置 |
||||
WEB_DOMAIN = "https://app.hehelucky.cn" # 用于超级签跳转配置,该域名一般为前端页面域名 |
||||
``` |
||||
|
||||
##### fir_client配置文件 ```fir_client/vue.confjg.js``` |
||||
```javascript |
||||
const pro_base_env = { |
||||
baseUrl: '/', //该选项可以填写web-api的域名,类似 https://api.xxx.com/ |
||||
index_static: '/', //若配置cdn等加速,可以填写cdn加速域名 |
||||
baseShortUrl: '/', //该选项可以填写short-api的域名,也可以和web-api域名一样,类似 https://api.xxx.com/ |
||||
short_static: '/short/', //若配置cdn等加速,可以填写cdn加速域名 |
||||
version: version, |
||||
}; |
||||
``` |
||||
|
||||
### flyapps web端搭建 |
||||
###### npm编译环境 |
||||
```shell |
||||
dnf install npm -y |
||||
npm install -g n |
||||
n 12.13 # 安装12版本的node或者14版本 ,最新版本会有问题 |
||||
npm install -g yarn |
||||
``` |
||||
|
||||
|
||||
|
||||
###### 编译web端和下载页 |
||||
```shell |
||||
cd /data/flyapps/fir_client/ |
||||
vim vue.config.js #修改api接口地址 |
||||
# pro_base_env 正式环境信息 |
||||
# dev_base_env 开发环境信息 |
||||
|
||||
yarn install |
||||
yarn build index # 前端打包,输出目录 dist_index |
||||
yarn build short # 下载页打包,输出目录 dist_short |
||||
``` |
||||
|
||||
###### 编译web管理后台 |
||||
```shell |
||||
cd /data/flyapps/fir_admin/ |
||||
yarn install |
||||
yarn build:prod # 下载页打包,输出目录 dist |
||||
``` |
||||
|
||||
### nginx配置 |
||||
##### 安装nginx |
||||
```shell |
||||
dnf install nginx -y |
||||
``` |
||||
##### 将域名ssl证书解压到```/etc/nginx/conf.d/``` 目录中,并重命名为```域名.pem```,```域名.key```格式 |
||||
##### 拷贝虚拟主机配置文件 |
||||
```shell |
||||
cp /data/flyapps/nginx.conf.d/flyapps-vhost.conf /etc/nginx/conf.d/ |
||||
``` |
||||
1.创建web目录,并将打包好的web复制该目录 |
||||
```shell |
||||
mkdir -pv /data/{fir_client/short,fir_admin} |
||||
cp -a /data/flyapps/fir_client/dist_index/* /data/fir_client/ |
||||
cp -a /data/flyapps/fir_client/dist_short/* /data/fir_client/short/ |
||||
cp -a /data/flyapps/fir_admin/dist/* /data/fir_admin/ |
||||
chown nginx.nginx -R /data/{fir_client,fir_admin} |
||||
``` |
||||
2.启动nginx服务 |
||||
```shell |
||||
nginx -t |
||||
systemctl restart nginx |
||||
systemctl enable nginx |
||||
``` |
||||
|
||||
##### 添加redis和mariadb uwsgi本地解析 |
||||
```shell |
||||
echo '127.0.0.1 mariadb redis flyapps' >> /etc/hosts |
||||
``` |
||||
|
||||
###### 迁移数据库 |
||||
```shell |
||||
cd /data/flyapps/fir_ser/ |
||||
python manage.py makemigrations |
||||
python manage.py migrate |
||||
``` |
||||
|
||||
#### 启动api服务 |
||||
```shell |
||||
echo 'net.core.somaxconn=1024' >> /etc/sysctl.conf |
||||
sysctl -p |
||||
cd /data/flyapps/fir_ser/ |
||||
python manage.py start all -u nginx -usm 1 -d |
||||
``` |
||||
|
||||
##### 根据提示创建默认管理用户,用与访问管理后台 |
||||
```shell |
||||
python manage.py createsuperuser |
||||
``` |
||||
- 需要输入用户名,邮箱和密码 |
||||
- 用户名和密码用与登录管理后台 |
||||
- 邮箱和密码用与登录前端web |
@ -0,0 +1,67 @@ |
||||
version: '3.2' |
||||
|
||||
services: |
||||
buildflyapps: |
||||
image: 'flyapps' |
||||
build: |
||||
context: ../../fir_ser |
||||
dockerfile: Dockerfile |
||||
command: |
||||
- echo |
||||
- success |
||||
|
||||
buildclient: |
||||
container_name: buildclient |
||||
image: 'node:14.17.3' |
||||
working_dir: /fir_client |
||||
volumes: |
||||
- /etc/localtime:/etc/localtime:ro |
||||
- ../../fir_client:/fir_client |
||||
- ../../data/web/:/web |
||||
command: |
||||
- bash |
||||
- -c |
||||
- yarn config set registry https://registry.npm.taobao.org && yarn install && yarn build index && yarn build short && ([ ! -e /web/fir_client ] && \cp -a dist_index /web/fir_client || \cp -a dist_index/* /web/fir_client/) && ([ ! -e /web/fir_client/short ] && \cp -a dist_short /web/fir_client/short || \cp -a dist_short/* /web/fir_client/short/) && echo build success |
||||
|
||||
buildindex: |
||||
container_name: buildindex |
||||
image: 'node:14.17.3' |
||||
working_dir: /fir_client |
||||
volumes: |
||||
- /etc/localtime:/etc/localtime:ro |
||||
- ../../fir_client:/fir_client |
||||
- ../../data/web/:/web |
||||
command: |
||||
- bash |
||||
- -c |
||||
- yarn config set registry https://registry.npm.taobao.org && yarn install && yarn build index && ([ ! -e /web/fir_index ] && \cp -a dist_index /web/fir_index || \cp -a dist_index/* /web/fir_index/) && echo build success |
||||
|
||||
|
||||
|
||||
buildshort: |
||||
container_name: buildshort |
||||
image: 'node:14.17.3' |
||||
working_dir: /fir_client |
||||
volumes: |
||||
- /etc/localtime:/etc/localtime:ro |
||||
- ../../fir_client:/fir_client |
||||
- ../../data/web/:/web |
||||
command: |
||||
- sh |
||||
- -c |
||||
- yarn config set registry https://registry.npm.taobao.org && yarn install && yarn build short && ([ ! -e /web/fir_short ] && \cp -a dist_short /web/fir_short || \cp -a dist_short/* /web/fir_short/) && echo build success |
||||
|
||||
|
||||
buildadmin: |
||||
container_name: buildadmin |
||||
image: 'node:14.17.3' |
||||
working_dir: /fir_admin |
||||
volumes: |
||||
- /etc/localtime:/etc/localtime:ro |
||||
- ../../fir_admin:/fir_admin |
||||
- ../../data/web/:/web |
||||
command: |
||||
- sh |
||||
- -c |
||||
- yarn config set registry https://registry.npm.taobao.org && yarn install && yarn build:prod && ([ ! -e /web/fir_admin ] && \cp -a dist /web/fir_admin || \cp -a dist/* /web/fir_admin/) && echo build success |
||||
|
@ -0,0 +1,31 @@ |
||||
version: '3' |
||||
|
||||
networks: |
||||
flyapps: |
||||
external: true |
||||
name: flyapps |
||||
|
||||
services: |
||||
flyapps: |
||||
container_name: flyapps |
||||
restart: always |
||||
image: 'nineven/flyapps' |
||||
working_dir: /data/fir_ser |
||||
volumes: |
||||
- /etc/localtime:/etc/localtime:ro |
||||
- ../../fir_ser:/data/fir_ser |
||||
- ../../data/flyapps/files:/data/fir_ser/files |
||||
- ../../data/logs/flyapps/:/data/fir_ser/logs |
||||
- ../../data/flyapps/supersign/:/data/fir_ser/supersign |
||||
- ../../nginx.conf.d:/data/cert |
||||
networks: |
||||
flyapps: |
||||
ipv4_address: 172.31.31.100 |
||||
external_links: |
||||
- mariadb:mariadb |
||||
- redis:redis |
||||
sysctls: |
||||
- net.core.somaxconn=4096 |
||||
extra_hosts: |
||||
- "mariadb:172.31.31.1" |
||||
- "redis:172.31.31.1" |
@ -0,0 +1,48 @@ |
||||
version: '3' |
||||
|
||||
networks: |
||||
flyapps: |
||||
external: true |
||||
name: flyapps |
||||
|
||||
services: |
||||
flyapps: |
||||
container_name: flyapps |
||||
restart: always |
||||
image: 'nineven/flyapps' |
||||
working_dir: /data/fir_ser |
||||
volumes: |
||||
- /etc/localtime:/etc/localtime:ro |
||||
- ../../fir_ser:/data/fir_ser |
||||
- ../../data/flyapps/files:/data/fir_ser/files |
||||
- ../../data/logs/flyapps/:/data/fir_ser/logs |
||||
- ../../data/flyapps/supersign/:/data/fir_ser/supersign |
||||
- ../../nginx.conf.d:/data/cert |
||||
networks: |
||||
flyapps: |
||||
ipv4_address: 172.31.31.100 |
||||
external_links: |
||||
- mariadb:mariadb |
||||
- redis:redis |
||||
sysctls: |
||||
- net.core.somaxconn=4096 |
||||
nginx: |
||||
container_name: nginx |
||||
restart: always |
||||
image: 'nginx:1.21.3' |
||||
volumes: |
||||
- /etc/localtime:/etc/localtime:ro |
||||
- ../../data/web:/data |
||||
- ../../nginx.conf.d:/etc/nginx/conf.d |
||||
- ../../data/logs/nginx:/var/log/nginx |
||||
networks: |
||||
flyapps: |
||||
ipv4_address: 172.31.31.200 |
||||
ports: |
||||
- 80:80 |
||||
- 443:443 |
||||
- 3448:3448 |
||||
external_links: |
||||
- flyapps:flyapps |
||||
depends_on: |
||||
- flyapps |
@ -0,0 +1,7 @@ |
||||
#!/bin/bash |
||||
# |
||||
# |
||||
|
||||
for i in nginx flyapps mariadb redis buildclient buildshort buildadmin ;do echo $i;docker rm -f $i;done |
||||
|
||||
docker network rm flyapps |
@ -0,0 +1,10 @@ |
||||
#!/bin/bash |
||||
# |
||||
# |
||||
|
||||
|
||||
docker pull 'bitnami/mariadb:10.7.3' |
||||
docker pull 'bitnami/redis:6.2.7' |
||||
docker pull 'nginx:1.21.3' |
||||
docker pull 'nineven/flyapps:latest' |
||||
docker pull 'node:14.17.3' |
@ -0,0 +1,24 @@ |
||||
#!/bin/bash |
||||
# |
||||
# |
||||
|
||||
which dockerd |
||||
if [ $? -ne 0 ];then |
||||
dnf config-manager --add-repo=https://download.docker.com/linux/centos/docker-ce.repo |
||||
dnf install docker-ce -y |
||||
fi |
||||
#which docker-compose |
||||
#if [ $? -ne 0 ];then |
||||
# curl -L https://get.daocloud.io/docker/compose/releases/download/v2.5.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose |
||||
# chmod +x /usr/local/bin/docker-compose |
||||
#fi |
||||
|
||||
data_path="$(dirname $(dirname `pwd`))/data" |
||||
mkdir -pv ${data_path}/{flyapps/files,web,mariadb,redis,logs/{mariadb,nginx,flyapps}} |
||||
\cp $(dirname $(dirname `pwd`))/fir_ser/files/head_img.jpeg ${data_path}/flyapps/files/ |
||||
chown 1001.1001 -R ${data_path}/{flyapps,web,mariadb,redis,logs/{mariadb,nginx,flyapps}} |
||||
chown 101.101 -R ${data_path}/{flyapps,logs/flyapps} |
||||
systemctl start docker && docker network create flyapps --driver bridge --subnet=172.31.31.0/24 --gateway=172.31.31.1 |
||||
systemctl enable docker |
||||
systemctl status docker |
||||
|
@ -0,0 +1 @@ |
||||
Asia/Shanghai |
@ -0,0 +1,43 @@ |
||||
version: '3.2' |
||||
|
||||
|
||||
|
||||
networks: |
||||
flyapps: |
||||
external: true |
||||
name: flyapps |
||||
|
||||
services: |
||||
|
||||
mariadb: |
||||
image: bitnami/mariadb:10.7.3 |
||||
container_name: mariadb |
||||
restart: always |
||||
environment: |
||||
- MARIADB_ROOT_PASSWORD=rootIPD.xx2.19 |
||||
- MARIADB_DATABASE=flyapps |
||||
- MARIADB_USER=flyuser |
||||
- MARIADB_PASSWORD=KGzKjZpWBp4R4RSa |
||||
#- ALLOW_EMPTY_PASSWORD=yes |
||||
- MARIADB_ENABLE_SLOW_QUERY=1 |
||||
- MARIADB_LONG_QUERY_TIME=3 |
||||
- MARIADB_SKIP_TEST_DB=yes |
||||
- MARIADB_EXTRA_FLAGS=--max-connect-errors=3000 --max_connections=30000 |
||||
ports: |
||||
- 3306:3306 |
||||
networks: |
||||
flyapps: |
||||
ipv4_address: 172.31.31.90 |
||||
volumes: |
||||
- ../init/timezone:/etc/timezone:ro |
||||
- /etc/localtime:/etc/localtime:ro |
||||
- ../../data/mariadb:/bitnami/mariadb/data |
||||
- ../../data/logs/mariadb:/data/logs/mariadb |
||||
- ./server.cnf:/opt/bitnami/mariadb/conf/my_custom.cnf:ro |
||||
|
||||
# adminer: |
||||
# image: adminer |
||||
# ports: |
||||
# - 8080:8080 |
||||
# networks: |
||||
# - fungame |
@ -0,0 +1,108 @@ |
||||
# |
||||
# These groups are read by MariaDB server. |
||||
# Use it for options that only the server (but not clients) should see |
||||
# |
||||
# See the examples of server my.cnf files in /usr/share/mysql/ |
||||
# |
||||
|
||||
|
||||
# this is only for the mysqld standalone daemon |
||||
[mysqld] |
||||
binlog_cache_size = 192K |
||||
thread_stack = 384K |
||||
join_buffer_size = 4096K |
||||
query_cache_type = 1 |
||||
max_heap_table_size = 1024M |
||||
|
||||
default_storage_engine = InnoDB |
||||
performance_schema_max_table_instances = 400 |
||||
table_definition_cache = 400 |
||||
skip-external-locking |
||||
key_buffer_size = 512M |
||||
max_allowed_packet = 1G |
||||
table_open_cache = 1024 |
||||
sort_buffer_size = 2048K |
||||
net_buffer_length = 4K |
||||
read_buffer_size = 2048K |
||||
read_rnd_buffer_size = 1024K |
||||
myisam_sort_buffer_size = 16M |
||||
thread_cache_size = 192 |
||||
query_cache_size = 256M |
||||
tmp_table_size = 1024M |
||||
sql-mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES |
||||
|
||||
|
||||
max_connections = 30000 |
||||
max_connect_errors = 1000 |
||||
open_files_limit = 65535 |
||||
|
||||
expire_logs_days = 10 |
||||
#log_queries_not_using_indexes=on |
||||
|
||||
character-set-client-handshake = FALSE |
||||
character-set-server = utf8mb4 |
||||
collation-server = utf8mb4_general_ci |
||||
init_connect='SET NAMES utf8mb4' |
||||
#character-set-server=utf8 |
||||
skip_name_resolve |
||||
event_scheduler=1 |
||||
#skip-grant-tables |
||||
|
||||
|
||||
#innodb_data_home_dir = /var/lib/mysql/ |
||||
#innodb_data_file_path = ibdata1:10M:autoextend |
||||
#innodb_log_group_home_dir = /var/lib/mysql/ |
||||
#innodb_buffer_pool_size = 1024M |
||||
#innodb_log_file_size = 128M |
||||
#innodb_log_buffer_size = 32M |
||||
#innodb_flush_log_at_trx_commit = 1 |
||||
#innodb_lock_wait_timeout = 50 |
||||
#innodb_max_dirty_pages_pct = 90 |
||||
#innodb_read_io_threads = 4 |
||||
#innodb_write_io_threads = 4 |
||||
|
||||
|
||||
|
||||
# |
||||
# Allow server to accept connections on all interfaces. |
||||
# |
||||
#bind-address=0.0.0.0 |
||||
# |
||||
# this is only for embedded server |
||||
# This group is only read by MariaDB servers, not by MySQL. |
||||
# If you use the same .cnf file for MySQL and MariaDB, |
||||
# you can put MariaDB-only options here |
||||
[mariadb] |
||||
#autoset_open_files_limit |
||||
#enable_slow_query_log |
||||
|
||||
#audit |
||||
plugin_load_add=server_audit |
||||
server_audit_logging=on |
||||
server_audit_events=connect,query |
||||
server_audit=force_plus_permanent |
||||
server_audit_events=QUERY_DDL,QUERY_DML,CONNECT |
||||
server_audit_output_type=file |
||||
server_audit_file_rotate_now=on |
||||
server_audit_file_rotations=9 |
||||
server_audit_file_rotate_size=1G |
||||
server_audit_file_path=/data/logs/mariadb |
||||
|
||||
|
||||
log_error=/data/logs/mariadb/mariadb.err.log |
||||
|
||||
log_output=FILE |
||||
slow_query_log |
||||
long_query_time=3 |
||||
slow_query_log_file=/data/logs/mariadb/mariadb-slow.log |
||||
log_queries_not_using_indexes=ON #Logging Queries That Don't Use Indexes |
||||
|
||||
|
||||
|
||||
#server_id=2 |
||||
log-bin=/data/logs/mariadb/mysql-bin |
||||
|
||||
# This group is only read by MariaDB-10.5 servers. |
||||
# If you use the same .cnf file for MariaDB of different versions, |
||||
# use this group for options that older servers don't understand |
||||
|
@ -0,0 +1,25 @@ |
||||
version: '3.2' |
||||
|
||||
|
||||
networks: |
||||
flyapps: |
||||
external: true |
||||
name: flyapps |
||||
|
||||
services: |
||||
redis: |
||||
image: 'bitnami/redis:6.2.7' |
||||
container_name: redis |
||||
restart: always |
||||
volumes: |
||||
- ../init/timezone:/etc/timezone:ro |
||||
- /etc/localtime:/etc/localtime:ro |
||||
- ../../data/redis:/bitnami/redis/data |
||||
environment: |
||||
#- REDIS_REPLICATION_MODE=master |
||||
#- ALLOW_EMPTY_PASSWORD=yes |
||||
- REDIS_PASSWORD=nineven |
||||
networks: |
||||
- flyapps |
||||
#ports: |
||||
# - 6379:6379 |
@ -0,0 +1,6 @@ |
||||
#!/bin/bash |
||||
# |
||||
# |
||||
|
||||
cd ../build/ |
||||
docker compose up buildclient buildadmin |
@ -0,0 +1,9 @@ |
||||
#!/bin/bash |
||||
# |
||||
# |
||||
|
||||
cd ../mariadb/ && docker compose up -d |
||||
cd ../redis/ && docker compose up -d |
||||
|
||||
cd ../flyapps/ && docker compose up -d |
||||
docker logs -f flyapps |
@ -0,0 +1,10 @@ |
||||
#!/bin/bash |
||||
# |
||||
# |
||||
|
||||
|
||||
cd ../flyapps/ && docker compose down |
||||
|
||||
cd ../redis/ && docker compose down |
||||
|
||||
cd ../mariadb/ && docker compose down |
@ -0,0 +1,54 @@ |
||||
import request from '@/utils/request' |
||||
|
||||
export function getDeveloperList(query) { |
||||
return request({ |
||||
url: '/developer/info', |
||||
method: 'get', |
||||
params: query |
||||
}) |
||||
} |
||||
|
||||
export function getDeveloperInfo(pk) { |
||||
return request({ |
||||
url: '/developer/info/' + pk, |
||||
method: 'get' |
||||
}) |
||||
} |
||||
|
||||
export function updatedeveloperInfo(pk, data) { |
||||
return request({ |
||||
url: '/developer/info/' + pk, |
||||
method: 'put', |
||||
data |
||||
}) |
||||
} |
||||
|
||||
export function getBillList(query) { |
||||
return request({ |
||||
url: '/bill/info', |
||||
method: 'get', |
||||
params: query |
||||
}) |
||||
} |
||||
|
||||
export function addBillInfo(data) { |
||||
return request({ |
||||
url: '/bill/info', |
||||
method: 'post', |
||||
data |
||||
}) |
||||
} |
||||
export function delBillInfo(pk) { |
||||
return request({ |
||||
url: '/bill/info/' + pk, |
||||
method: 'delete' |
||||
}) |
||||
} |
||||
|
||||
export function getUserBillInfo(query) { |
||||
return request({ |
||||
url: '/bill/userinfo', |
||||
method: 'get', |
||||
params: query |
||||
}) |
||||
} |
@ -0,0 +1,10 @@ |
||||
import request from '@/utils/request' |
||||
|
||||
export function getDevicesList(query) { |
||||
return request({ |
||||
url: '/devices/info', |
||||
method: 'get', |
||||
params: query |
||||
}) |
||||
} |
||||
|
@ -0,0 +1,31 @@ |
||||
import request from '@/utils/request' |
||||
|
||||
export function getDomainList(query) { |
||||
return request({ |
||||
url: '/domain/info', |
||||
method: 'get', |
||||
params: query |
||||
}) |
||||
} |
||||
|
||||
export function getDomainInfos(pk) { |
||||
return request({ |
||||
url: '/domain/info/' + pk, |
||||
method: 'get' |
||||
}) |
||||
} |
||||
|
||||
export function updateDomainInfo(pk, data) { |
||||
return request({ |
||||
url: '/domain/info/' + pk, |
||||
method: 'put', |
||||
data |
||||
}) |
||||
} |
||||
|
||||
export function deleteDomain(pk) { |
||||
return request({ |
||||
url: '/domain/info/' + pk, |
||||
method: 'delete' |
||||
}) |
||||
} |
@ -0,0 +1,31 @@ |
||||
import request from '@/utils/request' |
||||
|
||||
export function getAppReportList(query) { |
||||
return request({ |
||||
url: '/report/info', |
||||
method: 'get', |
||||
params: query |
||||
}) |
||||
} |
||||
|
||||
export function getAppReportIfo(pk) { |
||||
return request({ |
||||
url: '/report/info/' + pk, |
||||
method: 'get' |
||||
}) |
||||
} |
||||
|
||||
export function updateAppReportIfo(pk, data) { |
||||
return request({ |
||||
url: '/report/info/' + pk, |
||||
method: 'put', |
||||
data |
||||
}) |
||||
} |
||||
|
||||
export function deleteAppReportIfo(pk) { |
||||
return request({ |
||||
url: '/report/info/' + pk, |
||||
method: 'delete' |
||||
}) |
||||
} |
@ -0,0 +1,31 @@ |
||||
import request from '@/utils/request' |
||||
|
||||
export function getWxBindList(query) { |
||||
return request({ |
||||
url: '/wxbind/info', |
||||
method: 'get', |
||||
params: query |
||||
}) |
||||
} |
||||
|
||||
export function getWxBindInfos(pk) { |
||||
return request({ |
||||
url: '/wxbind/info/' + pk, |
||||
method: 'get' |
||||
}) |
||||
} |
||||
|
||||
export function updateWxBindInfo(pk,data) { |
||||
return request({ |
||||
url: '/wxbind/info/' + pk, |
||||
method: 'put', |
||||
data |
||||
}) |
||||
} |
||||
|
||||
export function deleteWxBind(pk) { |
||||
return request({ |
||||
url: '/wxbind/info/' + pk, |
||||
method: 'delete' |
||||
}) |
||||
} |
@ -0,0 +1,146 @@ |
||||
<template> |
||||
<div class="app-container"> |
||||
<el-form ref="postForm" :model="postForm" label-width="100px" :disabled="!is_edit"> |
||||
<el-row> |
||||
<el-col :span="12"> |
||||
<el-form-item label="用户ID"> |
||||
<el-row :gutter="12"> |
||||
<el-col :span="16"> |
||||
<el-input :value="postForm.user_id" disabled /> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
<el-form-item v-if="postForm.app_info&& postForm.app_info.app_id" label="应用ID"> |
||||
<el-row :gutter="12"> |
||||
<el-col :span="16"> |
||||
<el-input v-model="postForm.app_id" disabled /> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
|
||||
<el-form-item v-if="postForm.app_info&& postForm.app_info.app_id" label="应用名称"> |
||||
<el-row :gutter="12"> |
||||
<el-col :span="16"> |
||||
<el-input v-model="postForm.app_info.name" disabled /> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
<el-form-item label="域名类型"> |
||||
<el-row :gutter="12"> |
||||
<el-col :span="16"> |
||||
<el-select v-model="postForm.domain_type" class="filter-item" disabled> |
||||
<el-option v-for="item in postForm.domain_type_choices" :key="item.id" :label="item.name" :value="item.id" /> |
||||
</el-select> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
<el-form-item label="创建时间" prop="timestamp"> |
||||
<el-row :gutter="20"> |
||||
<el-col :span="8"> |
||||
<el-date-picker :value="postForm.created_time" type="datetime" disabled /> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
|
||||
</el-col> |
||||
<el-col :span="12"> |
||||
|
||||
<el-form-item label="绑定的域名" label-width="160px"> |
||||
<el-row :gutter="12"> |
||||
<el-col :span="16"> |
||||
<el-input v-model="postForm.domain_name" /> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
|
||||
<el-form-item label="绑定状态" label-width="160px"> |
||||
<el-row :gutter="12"> |
||||
<el-col :span="16"> |
||||
<el-select v-model="postForm.is_enable" class="filter-item"> |
||||
<el-option v-for="item in domain_state_choices" :key="item.id" :label="item.name" :value="item.id" /> |
||||
</el-select> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
<el-form-item label="CnameID" label-width="160px"> |
||||
<el-row :gutter="12"> |
||||
<el-col :span="16"> |
||||
<el-input v-model="postForm.cname_id" disabled /> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form> |
||||
<el-col :span="9" style="float: right"> |
||||
<el-button v-if="!is_edit" type="primary" :disabled="postForm.id === postForm.used_id" @click="is_edit=true">修改</el-button> |
||||
<div v-else> |
||||
<el-button type="primary" @click="is_edit=false">取消</el-button> |
||||
<el-button type="primary" @click="updateData">保存修改</el-button> |
||||
</div> |
||||
</el-col> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import { getDomainInfos, updateDomainInfo } from '@/api/domain' |
||||
const domain_state_choices = [ |
||||
{ id: false, name: '继续绑定' }, |
||||
{ id: true, name: '绑定成功' } |
||||
] |
||||
const defaultForm = { |
||||
user_id: undefined, |
||||
app_info: undefined, |
||||
domain_type: undefined, |
||||
domain_name: undefined, |
||||
cname_id: undefined, |
||||
is_enable: undefined, |
||||
domain_type_choices: undefined, |
||||
created_time: undefined |
||||
} |
||||
|
||||
export default { |
||||
name: 'OrderDetail', |
||||
components: { }, filters: {}, |
||||
data() { |
||||
return { |
||||
postForm: Object.assign({}, defaultForm), |
||||
loading: false, |
||||
is_edit: false, |
||||
domain_state_choices, |
||||
id: '' |
||||
} |
||||
}, |
||||
computed: {}, |
||||
created() { |
||||
this.id = this.$route.params && this.$route.params.id |
||||
this.fetchData(this.id) |
||||
}, |
||||
methods: { |
||||
fetchData(id) { |
||||
getDomainInfos(id).then(response => { |
||||
if (response.data) { |
||||
this.postForm = response.data |
||||
} |
||||
}).catch(err => { |
||||
console.log(err) |
||||
}) |
||||
}, |
||||
updateData() { |
||||
updateDomainInfo(this.id, this.postForm).then(response => { |
||||
this.$message.success('更新成功') |
||||
this.postForm = response.data |
||||
}).catch(err => { |
||||
console.log(err) |
||||
}) |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style scoped> |
||||
.editor-container { |
||||
position: relative; |
||||
height: 100%; |
||||
} |
||||
</style> |
@ -0,0 +1,188 @@ |
||||
<template> |
||||
<div class="app-container"> |
||||
<div class="filter-container"> |
||||
<el-input v-model="listQuery.user_id" placeholder="用户ID" style="width: 140px;" class="filter-item" clearable @keyup.enter.native="handleFilter" /> |
||||
<el-input v-model="listQuery.domain_name" placeholder="下载域名" style="width: 300px;" class="filter-item" clearable @keyup.enter.native="handleFilter" /> |
||||
<el-input v-model="listQuery.app_name" placeholder="应用名称" style="width: 200px;" class="filter-item" clearable @keyup.enter.native="handleFilter" /> |
||||
<el-select v-model="listQuery.domain_type" placeholder="下载域名类型" clearable class="filter-item" style="width: 140px" @change="handleFilter"> |
||||
<el-option v-for="item in domain_type_choices" :key="item.id" :label="item.name" :value="item.id" /> |
||||
</el-select> |
||||
<el-select v-model="listQuery.is_enable" placeholder="域名绑定状态" clearable class="filter-item" style="width: 140px" @change="handleFilter"> |
||||
<el-option v-for="item in domain_state_choices" :key="item.id" :label="item.name" :value="item.id" /> |
||||
</el-select> |
||||
<el-select v-model="listQuery.ordering" style="width: 140px" class="filter-item" @change="handleFilter"> |
||||
<el-option v-for="item in sortOptions" :key="item.key" :label="item.label" :value="item.key" /> |
||||
</el-select> |
||||
<el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter"> |
||||
Search |
||||
</el-button> |
||||
</div> |
||||
<el-table |
||||
v-loading="listLoading" |
||||
:data="list" |
||||
element-loading-text="Loading" |
||||
border |
||||
fit |
||||
highlight-current-row |
||||
stripe |
||||
> |
||||
<el-table-column align="center" label="ID" width="90"> |
||||
<template slot-scope="scope"> |
||||
{{ scope.row.id }} |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="用户ID" width="100" align="center"> |
||||
<template slot-scope="scope"> |
||||
<router-link :to="{name: 'user_info_edit',params:{id:scope.row.user_id}}"> |
||||
<el-link type="primary"> {{ scope.row.user_id }}</el-link> |
||||
</router-link> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="下载域名" min-width="280px" align="center"> |
||||
<template slot-scope="scope"> |
||||
{{ scope.row.domain_name }} |
||||
</template> |
||||
</el-table-column> |
||||
|
||||
<el-table-column class-name="status-col" label="下载域名类型" width="160" align="center"> |
||||
<template slot-scope="scope"> |
||||
<router-link v-if="scope.row.domain_type===2" :to="{name: 'app_info_list',params:{user_id:scope.row.user_id,app_id:scope.row.app_id}}"> |
||||
<el-tag :type="scope.row.domain_type | domainStatusFilter">{{ scope.row| domainLableFilter }}</el-tag> |
||||
</router-link> |
||||
<el-tag v-else :type="scope.row.domain_type | domainStatusFilter">{{ scope.row| domainLableFilter }}</el-tag> |
||||
|
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column class-name="status-col" label="绑定状态" width="95" align="center"> |
||||
<template slot-scope="scope"> |
||||
<el-tag :type="scope.row.is_enable | statusFilter">{{ scope.row| statusLableFilter }}</el-tag> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column align="center" prop="created_time" label="创建时间" width="120"> |
||||
<template slot-scope="scope"> |
||||
<i class="el-icon-time" /> |
||||
<el-tooltip :content="scope.row.created_time"> |
||||
<span>{{ scope.row.created_time|formatTime }}</span> |
||||
</el-tooltip> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="操作" align="center" width="160" class-name="small-padding fixed-width"> |
||||
<template slot-scope="scope"> |
||||
<router-link :to="{name: 'domain_info_edit',params:{id:scope.row.id}}"> |
||||
<el-button type="primary" size="mini"> |
||||
查看编辑 |
||||
</el-button> |
||||
</router-link> |
||||
<el-button type="danger" size="mini" @click="remove_domain(scope.row.id)"> |
||||
删除 |
||||
</el-button> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
<pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" @pagination="fetchData" /> |
||||
|
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import { deleteDomain, getDomainList } from '@/api/domain' |
||||
import { baseFilter } from '@/utils' |
||||
import Pagination from '@/components/Pagination' // secondary package based on el-pagination |
||||
import waves from '@/directive/waves' // waves directive |
||||
|
||||
const sortOptions = [ |
||||
{ label: '创建时间 Ascending', key: 'created_time' }, |
||||
{ label: '创建时间 Descending', key: '-created_time' } |
||||
] |
||||
|
||||
const domain_state_choices = [ |
||||
{ id: false, name: '继续绑定' }, |
||||
{ id: true, name: '绑定成功' } |
||||
] |
||||
|
||||
export default { |
||||
name: 'DomainInfo', |
||||
components: { Pagination }, |
||||
directives: { waves }, |
||||
filters: { |
||||
formatTime(time) { |
||||
if (time) { |
||||
return time.split('T')[0] |
||||
} |
||||
}, |
||||
domainStatusFilter(status) { |
||||
const statusMap = { |
||||
'1': 'success', |
||||
'0': 'gray', |
||||
'2': 'info' } |
||||
return statusMap[status] |
||||
}, |
||||
domainLableFilter(row) { |
||||
if (row.domain_type === 2) { |
||||
return '应用' + row.app_info.name + '域名' |
||||
} |
||||
return baseFilter(row.domain_type, row.domain_type_choices) |
||||
}, |
||||
statusLableFilter(row) { |
||||
return baseFilter(row.is_enable, domain_state_choices) |
||||
}, |
||||
statusFilter(status) { |
||||
const statusMap = { |
||||
true: 'success', |
||||
false: 'danger' |
||||
} |
||||
return statusMap[status] |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
list: null, |
||||
listLoading: true, |
||||
total: 0, |
||||
listQuery: { |
||||
page: 1, |
||||
limit: 10, |
||||
user_id: undefined, |
||||
ordering: '-created_time', |
||||
domain_name: undefined, |
||||
app_name: undefined, |
||||
domain_type: undefined, |
||||
is_enable: undefined |
||||
}, |
||||
sortOptions, |
||||
domain_type_choices: [], |
||||
domain_state_choices |
||||
} |
||||
}, |
||||
created() { |
||||
this.fetchData() |
||||
}, mounted() { |
||||
if (this.$route.params.user_id) { |
||||
this.listQuery.user_id = this.$route.params.user_id |
||||
} |
||||
console.log(this.$router) |
||||
}, |
||||
methods: { |
||||
remove_domain(domain_id) { |
||||
deleteDomain(domain_id).then(response => { |
||||
this.fetchData() |
||||
}) |
||||
}, |
||||
handleFilter() { |
||||
this.listQuery.page = 1 |
||||
this.fetchData() |
||||
}, |
||||
fetchData() { |
||||
this.listLoading = true |
||||
getDomainList(this.listQuery).then(response => { |
||||
this.list = response.data.results |
||||
if (this.list && this.list.length > 0) { |
||||
this.domain_type_choices = this.list[0].domain_type_choices |
||||
} |
||||
this.total = response.data.count |
||||
this.listLoading = false |
||||
}) |
||||
} |
||||
} |
||||
} |
||||
</script> |
@ -0,0 +1,158 @@ |
||||
<template> |
||||
<div class="app-container"> |
||||
<el-form ref="postForm" :model="postForm" label-width="100px" :disabled="!is_edit"> |
||||
<el-row> |
||||
<el-col :span="12"> |
||||
<el-form-item label="应用ID"> |
||||
<el-row :gutter="12"> |
||||
<el-col :span="16"> |
||||
<el-input :value="postForm.app_id" disabled /> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
<el-form-item label="应用名称"> |
||||
<el-row :gutter="12"> |
||||
<el-col :span="16"> |
||||
<el-input v-model="postForm.app_name" disabled /> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
<el-form-item label="举报类型"> |
||||
<el-row :gutter="12"> |
||||
<el-col :span="16"> |
||||
<el-select v-model="postForm.report_type" class="filter-item" disabled> |
||||
<el-option v-for="item in postForm.report_type_choices" :key="item.id" :label="item.name" :value="item.id" /> |
||||
</el-select> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
<el-form-item label="创建时间" prop="timestamp"> |
||||
<el-row :gutter="20"> |
||||
<el-col :span="8"> |
||||
<el-date-picker :value="postForm.created_time" type="datetime" disabled /> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
|
||||
<el-form-item label="举报原因"> |
||||
<el-row :gutter="12"> |
||||
<el-col :span="16"> |
||||
<el-input v-model="postForm.report_reason" :autosize="{ minRows: 4, maxRows: 6}" type="textarea" disabled /> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
</el-col> |
||||
<el-col :span="12"> |
||||
|
||||
<el-form-item label="举报者姓名" label-width="160px"> |
||||
<el-row :gutter="12"> |
||||
<el-col :span="16"> |
||||
<el-input v-model="postForm.username" disabled /> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
|
||||
<el-form-item label="举报联系方式" label-width="160px"> |
||||
<el-row :gutter="12"> |
||||
<el-col :span="16"> |
||||
<el-input v-model="postForm.email" disabled /> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
<el-form-item label="举报者IP地址" label-width="160px"> |
||||
<el-row :gutter="12"> |
||||
<el-col :span="16"> |
||||
<el-input v-model="postForm.remote_addr" disabled /> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
<el-form-item label="处理状态" label-width="160px"> |
||||
<el-row :gutter="12"> |
||||
<el-col :span="16"> |
||||
<el-select v-model="postForm.status" class="filter-item"> |
||||
<el-option v-for="item in postForm.status_choices" :key="item.id" :label="item.name" :value="item.id" /> |
||||
</el-select> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
<el-form-item label="处理备注" label-width="160px"> |
||||
<el-row :gutter="12"> |
||||
<el-col :span="16"> |
||||
<el-input v-model="postForm.description" :autosize="{ minRows: 4, maxRows: 6}" type="textarea" /> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form> |
||||
<el-col :span="9" style="float: right"> |
||||
<el-button v-if="!is_edit" type="primary" :disabled="postForm.id === postForm.used_id" @click="is_edit=true">修改</el-button> |
||||
<div v-else> |
||||
<el-button type="primary" @click="is_edit=false">取消</el-button> |
||||
<el-button type="primary" @click="updateData">保存修改</el-button> |
||||
</div> |
||||
</el-col> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import { getAppReportIfo, updateAppReportIfo } from '@/api/report' |
||||
|
||||
const defaultForm = { |
||||
app_id: undefined, |
||||
app_name: undefined, |
||||
bundle_id: undefined, |
||||
created_time: undefined, |
||||
description: undefined, |
||||
email: undefined, |
||||
remote_addr: undefined, |
||||
report_reason: undefined, |
||||
status: undefined, |
||||
report_type: undefined, |
||||
username: undefined |
||||
} |
||||
|
||||
export default { |
||||
name: 'ReportDetail', |
||||
components: { }, filters: {}, |
||||
data() { |
||||
return { |
||||
postForm: Object.assign({}, defaultForm), |
||||
loading: false, |
||||
is_edit: false, |
||||
id: '' |
||||
} |
||||
}, |
||||
computed: {}, |
||||
created() { |
||||
this.id = this.$route.params && this.$route.params.id |
||||
this.fetchData(this.id) |
||||
}, |
||||
methods: { |
||||
fetchData(id) { |
||||
getAppReportIfo(this.id).then(response => { |
||||
if (response.data) { |
||||
this.postForm = response.data |
||||
} |
||||
}).catch(err => { |
||||
console.log(err) |
||||
}) |
||||
}, |
||||
updateData() { |
||||
updateAppReportIfo(this.id, this.postForm).then(response => { |
||||
this.$message.success('更新成功') |
||||
this.postForm = response.data |
||||
}).catch(err => { |
||||
console.log(err) |
||||
}) |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style scoped> |
||||
.editor-container { |
||||
position: relative; |
||||
height: 100%; |
||||
} |
||||
</style> |
@ -0,0 +1,227 @@ |
||||
<template> |
||||
<div class="app-container"> |
||||
<div class="filter-container"> |
||||
<el-input v-model="listQuery.app_id" placeholder="应用ID" style="width: 140px;" class="filter-item" clearable @keyup.enter.native="handleFilter" /> |
||||
<el-input v-model="listQuery.app_name" placeholder="应用名称" style="width: 140px;" class="filter-item" clearable @keyup.enter.native="handleFilter" /> |
||||
<el-input v-model="listQuery.bundle_id" placeholder="Bundle_Id" style="width: 300px;" class="filter-item" clearable @keyup.enter.native="handleFilter" /> |
||||
<el-input v-model="listQuery.remote_addr" placeholder="远端地址" style="width: 200px;" class="filter-item" clearable @keyup.enter.native="handleFilter" /> |
||||
<el-input v-model="listQuery.email" placeholder="联系信息" style="width: 200px;" class="filter-item" clearable @keyup.enter.native="handleFilter" /> |
||||
<el-select v-model="listQuery.report_type" placeholder="举报类型" clearable class="filter-item" style="width: 140px" @change="handleFilter"> |
||||
<el-option v-for="item in report_type_choices" :key="item.id" :label="item.name" :value="item.id" /> |
||||
</el-select> |
||||
<el-select v-model="listQuery.status" placeholder="处理状态" clearable class="filter-item" style="width: 140px" @change="handleFilter"> |
||||
<el-option v-for="item in status_choices" :key="item.id" :label="item.name" :value="item.id" /> |
||||
</el-select> |
||||
|
||||
<el-select v-model="listQuery.ordering" style="width: 140px" class="filter-item" @change="handleFilter"> |
||||
<el-option v-for="item in sortOptions" :key="item.key" :label="item.label" :value="item.key" /> |
||||
</el-select> |
||||
<el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter"> |
||||
Search |
||||
</el-button> |
||||
</div> |
||||
<el-table |
||||
v-loading="listLoading" |
||||
:data="list" |
||||
element-loading-text="Loading" |
||||
border |
||||
fit |
||||
highlight-current-row |
||||
stripe |
||||
> |
||||
<el-table-column align="center" label="ID" width="90"> |
||||
<template slot-scope="scope"> |
||||
{{ scope.row.id }} |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="应用ID" width="100" align="center"> |
||||
<template slot-scope="scope"> |
||||
<router-link :to="{name: 'app_info_edit',params:{id:scope.row.app_id}}"> |
||||
<el-link type="primary"> {{ scope.row.app_id }}</el-link> |
||||
</router-link> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="应用名称" width="80px"> |
||||
<template slot-scope="scope"> |
||||
{{ scope.row.app_name }} |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="Bundle_Id" align="center"> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.bundle_id }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="联系信息" align="center"> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.email }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="联系姓名" align="center"> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.username }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="举报者IP" align="center"> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.remote_addr }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column class-name="status-col" label="举报类型" width="95" align="center"> |
||||
<template slot-scope="scope"> |
||||
<el-tag :type="scope.row.report_type | payStatusFilter">{{ scope.row| payLableFilter }}</el-tag> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column class-name="status-col" label="处理状态" width="95" align="center"> |
||||
<template slot-scope="scope"> |
||||
<el-tag :type="scope.row.status | certStatusFilter">{{ scope.row| statusLableFilter }}</el-tag> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column align="center" prop="created_time" label="提交时间" width="120"> |
||||
<template slot-scope="scope"> |
||||
<i class="el-icon-time" /> |
||||
<el-tooltip :content="scope.row.created_time"> |
||||
<span>{{ scope.row.created_time|formatTime }}</span> |
||||
</el-tooltip> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="操作" align="center" width="160" class-name="small-padding fixed-width"> |
||||
<template slot-scope="scope"> |
||||
<router-link :to="{name: 'report_info_edit',params:{id:scope.row.id}}"> |
||||
<el-button type="primary" size="mini"> |
||||
查看编辑 |
||||
</el-button> |
||||
</router-link> |
||||
<el-button type="danger" size="mini" @click="remove_order_info(scope.row)"> |
||||
删除 |
||||
</el-button> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
<pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" @pagination="fetchData" /> |
||||
|
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import { deleteAppReportIfo, getAppReportList } from '@/api/report' |
||||
import { baseFilter } from '@/utils' |
||||
import Pagination from '@/components/Pagination' // secondary package based on el-pagination |
||||
import waves from '@/directive/waves' // waves directive |
||||
|
||||
const sortOptions = [ |
||||
{ label: '创建时间 Ascending', key: 'created_time' }, |
||||
{ label: '创建时间 Descending', key: '-created_time' } |
||||
] |
||||
|
||||
export default { |
||||
name: 'OrderInfo', |
||||
components: { Pagination }, |
||||
directives: { waves }, |
||||
filters: { |
||||
formatTime(time) { |
||||
if (time) { |
||||
return time.split('T')[0] |
||||
} |
||||
}, |
||||
payStatusFilter(status) { |
||||
const statusMap = { |
||||
'0': 'gray', |
||||
'1': 'success' } |
||||
return statusMap[status] |
||||
}, |
||||
certStatusFilter(status) { |
||||
const statusMap = { |
||||
'0': 'success', |
||||
'1': 'info', |
||||
'2': 'gray' } |
||||
return statusMap[status] |
||||
}, |
||||
payLableFilter(row) { |
||||
return baseFilter(row.report_type, row.report_type_choices) |
||||
}, |
||||
statusLableFilter(row) { |
||||
return baseFilter(row.status, row.status_choices) |
||||
}, |
||||
statusFilter(status) { |
||||
const statusMap = { |
||||
true: 'success', |
||||
false: 'danger' |
||||
} |
||||
return statusMap[status] |
||||
}, |
||||
appStatusNameFilter(row) { |
||||
for (const r of row.status_choices) { |
||||
if (r.id === row.status) { |
||||
return r.name |
||||
} |
||||
} |
||||
}, |
||||
appStatusFilter(status) { |
||||
const statusMap = { |
||||
'0': 'danger', |
||||
'1': 'success', |
||||
'2': 'gray' |
||||
} |
||||
return statusMap[status] |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
list: null, |
||||
listLoading: true, |
||||
total: 0, |
||||
listQuery: { |
||||
page: 1, |
||||
limit: 10, |
||||
app_id: undefined, |
||||
ordering: '-created_time', |
||||
report_type: undefined, |
||||
app_name: undefined, |
||||
bundle_id: undefined, |
||||
email: undefined, |
||||
status: undefined, |
||||
remote_addr: undefined, |
||||
username: undefined |
||||
}, |
||||
sortOptions, |
||||
report_type_choices: [], |
||||
status_choices: [] |
||||
} |
||||
}, |
||||
created() { |
||||
this.fetchData() |
||||
}, mounted() { |
||||
if (this.$route.params.user_id) { |
||||
this.listQuery.user_id = this.$route.params.user_id |
||||
} |
||||
}, |
||||
methods: { |
||||
remove_order_info(order_info) { |
||||
deleteAppReportIfo(order_info.id).then(response => { |
||||
this.list = response.data |
||||
if (response.code === 1000) { |
||||
this.fetchData() |
||||
} else { |
||||
this.$message.error('操作失败了 ' + response.msg) |
||||
} |
||||
}) |
||||
}, |
||||
handleFilter() { |
||||
this.listQuery.page = 1 |
||||
this.fetchData() |
||||
}, |
||||
fetchData() { |
||||
this.listLoading = true |
||||
getAppReportList(this.listQuery).then(response => { |
||||
this.list = response.data.results |
||||
if (this.list && this.list.length > 0) { |
||||
this.report_type_choices = this.list[0].report_type_choices |
||||
this.status_choices = this.list[0].status_choices |
||||
} |
||||
this.total = response.data.count |
||||
this.listLoading = false |
||||
}) |
||||
} |
||||
} |
||||
} |
||||
</script> |
@ -1,183 +0,0 @@ |
||||
<template> |
||||
<div class="app-container"> |
||||
<el-form ref="postForm" :model="postForm" label-width="100px" :disabled="!is_edit"> |
||||
<el-row> |
||||
<el-col :span="12"> |
||||
<el-form-item label="用户ID"> |
||||
<el-row :gutter="12"> |
||||
<el-col :span="16"> |
||||
<el-input :value="postForm.user_id" disabled /> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
<el-form-item label="存储名称"> |
||||
<el-row :gutter="12"> |
||||
<el-col :span="16"> |
||||
<el-input v-model="postForm.name" /> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
<el-form-item label="存储类型"> |
||||
<el-row :gutter="12"> |
||||
<el-col :span="16"> |
||||
<el-select v-model="postForm.storage_type" class="filter-item" disabled> |
||||
<el-option v-for="item in postForm.storage_choices" :key="item.id" :label="item.name" :value="item.id" /> |
||||
</el-select> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
<el-form-item label="创建时间" prop="timestamp"> |
||||
<el-row :gutter="20"> |
||||
<el-col :span="8"> |
||||
<el-date-picker :value="postForm.created_time" type="datetime" disabled /> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
<el-form-item label="更新时间" prop="timestamp"> |
||||
<el-row :gutter="20"> |
||||
<el-col :span="8"> |
||||
<el-date-picker :value="postForm.updated_time" type="datetime" disabled /> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
<el-form-item label="存储描述信息"> |
||||
<el-row :gutter="12"> |
||||
<el-col :span="16"> |
||||
<el-input v-model="postForm.description" :autosize="{ minRows: 4, maxRows: 6}" type="textarea" /> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
</el-col> |
||||
<el-col :span="12"> |
||||
|
||||
<el-form-item label="存储访问access_key" label-width="160px"> |
||||
<el-row :gutter="12"> |
||||
<el-col :span="16"> |
||||
<el-input v-model="postForm.access_key" /> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
<el-form-item label="存储访问secret_key" label-width="160px"> |
||||
<el-row :gutter="12"> |
||||
<el-col :span="16"> |
||||
<el-input v-model="postForm.secret_key" /> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
<el-form-item label="存储空间bucket_name" label-width="160px"> |
||||
<el-row :gutter="12"> |
||||
<el-col :span="16"> |
||||
<el-input v-model="postForm.bucket_name" /> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
<div v-if="postForm.storage_type===2"> |
||||
<el-form-item label="阿里云sts_role_arn" label-width="160px"> |
||||
<el-row :gutter="12"> |
||||
<el-col :span="16"> |
||||
<el-input v-model="postForm.sts_role_arn" /> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
|
||||
<el-form-item label="阿里云endpoint" label-width="160px"> |
||||
<el-row :gutter="12"> |
||||
<el-col :span="16"> |
||||
<el-input v-model="postForm.endpoint" /> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
<el-form-item label="阿里云下载授权方式" label-width="160px"> |
||||
<el-row :gutter="12"> |
||||
<el-col :span="16"> |
||||
<el-select v-model="postForm.download_auth_type" class="filter-item" style="width: 100%"> |
||||
<el-option v-for="item in postForm.download_auth_type_choices" :key="item.id" :label="item.name" :value="item.id" /> |
||||
</el-select> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
<el-form-item v-if="postForm.download_auth_type===2" label="阿里云cnd_auth_key" label-width="160px"> |
||||
<el-row :gutter="12"> |
||||
<el-col :span="16"> |
||||
<el-input v-model="postForm.cnd_auth_key" /> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
</div> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form> |
||||
<el-col :span="9" style="float: right"> |
||||
<el-button v-if="!is_edit" type="primary" @click="is_edit=true">修改</el-button> |
||||
<div v-else> |
||||
<el-button type="primary" @click="is_edit=false">取消</el-button> |
||||
<el-button type="primary" @click="updateData">保存修改</el-button> |
||||
</div> |
||||
</el-col> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import { getStorageInfo, updateStorageInfo } from '@/api/storage' |
||||
|
||||
const defaultForm = { |
||||
user_id: undefined, |
||||
name: undefined, |
||||
storage_type: undefined, |
||||
access_key: undefined, |
||||
secret_key: undefined, |
||||
bucket_name: undefined, |
||||
domain_name: undefined, |
||||
created_time: undefined, |
||||
description: undefined, |
||||
sts_role_arn: undefined, |
||||
endpoint: undefined, |
||||
download_auth_type: undefined, |
||||
cnd_auth_key: undefined, |
||||
updated_time: undefined, |
||||
download_auth_type_choices: [] |
||||
} |
||||
|
||||
export default { |
||||
name: 'StorageDetail', |
||||
components: { }, filters: {}, |
||||
data() { |
||||
return { |
||||
postForm: Object.assign({}, defaultForm), |
||||
loading: false, |
||||
is_edit: false |
||||
} |
||||
}, |
||||
computed: {}, |
||||
created() { |
||||
const id = this.$route.params && this.$route.params.id |
||||
this.fetchData(id) |
||||
}, |
||||
methods: { |
||||
fetchData(id) { |
||||
getStorageInfo({ id: id }).then(response => { |
||||
if (response.data.length === 1) { |
||||
this.postForm = response.data[0] |
||||
} |
||||
}).catch(err => { |
||||
console.log(err) |
||||
}) |
||||
}, |
||||
updateData() { |
||||
updateStorageInfo(this.postForm).then(response => { |
||||
this.$message.success('更新成功') |
||||
this.postForm = response.data |
||||
}).catch(err => { |
||||
console.log(err) |
||||
}) |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style scoped> |
||||
.editor-container { |
||||
position: relative; |
||||
height: 100%; |
||||
} |
||||
</style> |
@ -0,0 +1,117 @@ |
||||
<template> |
||||
<div class="app-container"> |
||||
<el-form ref="postForm" :model="postForm" label-width="100px"> |
||||
<el-row> |
||||
<el-col :span="12"> |
||||
<el-form-item label="用户ID"> |
||||
<el-row :gutter="12"> |
||||
<el-col :span="16"> |
||||
<el-input v-model="postForm.user_id" placeholder="邮箱,手机号,或者uid" /> |
||||
</el-col> |
||||
<el-col :span="4"> |
||||
<el-button @click="check_balance('user_id')">查询校验</el-button> |
||||
</el-col> |
||||
</el-row> |
||||
<el-row v-if="user_info.private_balance_info.all_balance+user_info.public_balance_info.all_balance"> |
||||
<el-col> |
||||
<el-link :underline="false"> 公有池数量 {{ user_info.public_balance_info.all_balance }} 已经使用数量 {{ user_info.public_balance_info.used_balance }}</el-link> |
||||
</el-col> |
||||
<el-col> |
||||
<el-link :underline="false"> 私有池数量 {{ user_info.private_balance_info.all_balance }} 已经使用数量 {{ user_info.private_balance_info.used_balance }}</el-link> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
<el-form-item label="目标用户"> |
||||
<el-row :gutter="12"> |
||||
<el-col :span="16"> |
||||
<el-input v-model="postForm.to_user_id" placeholder="邮箱,手机号,或者uid" /> |
||||
</el-col> |
||||
<el-col :span="4"> |
||||
<el-button @click="check_balance('to_user_id')">查询校验</el-button> |
||||
</el-col> |
||||
</el-row> |
||||
<el-row v-if="to_user_info.private_balance_info.all_balance+to_user_info.public_balance_info.all_balance"> |
||||
<el-col> |
||||
<el-link :underline="false"> 公有池数量 {{ to_user_info.public_balance_info.all_balance }} 已经使用数量 {{ to_user_info.public_balance_info.used_balance }}</el-link> |
||||
</el-col> |
||||
<el-col> |
||||
<el-link :underline="false"> 私有池数量 {{ to_user_info.private_balance_info.all_balance }} 已经使用数量 {{ to_user_info.private_balance_info.used_balance }}</el-link> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
<el-form-item label="转移数量"> |
||||
<el-row :gutter="12"> |
||||
<el-col :span="16"> |
||||
<el-input-number v-model="postForm.number" :min="0" :max="10000" label="可使用设备数" /> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form> |
||||
<el-col :span="9" style="float: right"> |
||||
<el-button type="primary" @click="addbill">确定</el-button> |
||||
</el-col> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import waves from '@/directive/waves' |
||||
import { addBillInfo, getUserBillInfo } from '@/api/developer' |
||||
|
||||
const sortOptions = [ |
||||
{ label: '创建时间 Ascending', key: 'created_time' }, |
||||
{ label: '创建时间 Descending', key: '-created_time' } |
||||
] |
||||
|
||||
|
||||
export default { |
||||
name: 'BillAddInfo', |
||||
directives: { waves }, |
||||
filters: { |
||||
formatTime(time) { |
||||
return time.split('T')[0] |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
list: null, |
||||
listLoading: true, |
||||
total: 0, |
||||
postForm: { |
||||
to_user_id: undefined, |
||||
user_id: undefined, |
||||
number: undefined |
||||
}, |
||||
user_info: { public_balance_info: { all_balance: undefined }, private_balance_info: { used_balance: undefined }}, |
||||
to_user_info: { public_balance_info: { all_balance: undefined }, private_balance_info: { used_balance: undefined }}, |
||||
action_choices: undefined, |
||||
sortOptions |
||||
} |
||||
}, |
||||
created() { |
||||
|
||||
}, |
||||
methods: { |
||||
check_balance(act) { |
||||
let user_id = this.postForm.user_id |
||||
if (act === 'to_user_id') { |
||||
user_id = this.postForm.to_user_id |
||||
} |
||||
getUserBillInfo({ user_id: user_id }).then(response => { |
||||
if (act === 'user_id') { |
||||
this.user_info = response |
||||
} else if (act === 'to_user_id') { |
||||
this.to_user_info = response |
||||
} |
||||
console.log(this.user_info) |
||||
}) |
||||
}, |
||||
addbill() { |
||||
addBillInfo(this.postForm).then(response => { |
||||
this.$message.success('充值成功') |
||||
}) |
||||
} |
||||
} |
||||
} |
||||
</script> |
@ -0,0 +1,202 @@ |
||||
<template> |
||||
<div class="app-container"> |
||||
<div class="filter-container"> |
||||
<el-input v-model="listQuery.user_id" placeholder="用户ID" style="width: 140px;" class="filter-item" clearable @keyup.enter.native="handleFilter" /> |
||||
<el-input v-model="listQuery.to_user_id" placeholder="目标用户" style="width: 300px;" class="filter-item" clearable @keyup.enter.native="handleFilter" /> |
||||
<el-input v-model="listQuery.udid" placeholder="设备UDID" style="width: 200px;" class="filter-item" clearable @keyup.enter.native="handleFilter" /> |
||||
<el-input v-model="listQuery.app_id" placeholder="应用id" style="width: 200px;" class="filter-item" clearable @keyup.enter.native="handleFilter" /> |
||||
<el-select v-model="listQuery.action" placeholder="充值类型" clearable class="filter-item" style="width: 140px" @change="handleFilter"> |
||||
<el-option v-for="item in action_choices" :key="item.id" :label="item.name" :value="item.id" /> |
||||
</el-select> |
||||
<el-select v-model="listQuery.ordering" style="width: 140px" class="filter-item" @change="handleFilter"> |
||||
<el-option v-for="item in sortOptions" :key="item.key" :label="item.label" :value="item.key" /> |
||||
</el-select> |
||||
<el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter"> |
||||
Search |
||||
</el-button> |
||||
</div> |
||||
<el-table |
||||
v-loading="listLoading" |
||||
:data="list" |
||||
element-loading-text="Loading" |
||||
border |
||||
fit |
||||
highlight-current-row |
||||
stripe |
||||
> |
||||
<el-table-column align="center" label="ID" width="90"> |
||||
<template slot-scope="scope"> |
||||
{{ scope.row.id }} |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="用户ID" width="100" align="center"> |
||||
<template slot-scope="scope"> |
||||
<router-link :to="{name: 'user_info_edit',params:{id:scope.row.user_id}}"> |
||||
<el-link type="primary"> {{ scope.row.user_id }}</el-link> |
||||
</router-link> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="目标用户ID" width="100" align="center"> |
||||
<template slot-scope="scope"> |
||||
<router-link v-if="scope.row.to_user_id" :to="{name: 'user_info_edit',params:{id:scope.row.to_user_id}}"> |
||||
<el-link type="primary"> {{ scope.row.to_user_id }}</el-link> |
||||
</router-link> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="应用ID" width="100" align="center"> |
||||
<template slot-scope="scope"> |
||||
<router-link v-if="scope.row.app_id" :to="{name: 'app_info_edit',params:{id:scope.row.app_id}}"> |
||||
<el-link type="primary"> {{ scope.row.app_id }}</el-link> |
||||
</router-link> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="UDID" align="center"> |
||||
<template slot-scope="scope"> |
||||
{{ scope.row.udid }} |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="客户端IP" align="center" > |
||||
<template slot-scope="scope"> |
||||
{{ scope.row.remote_addr }} |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="账单类型" align="center" width="100"> |
||||
<template slot-scope="scope"> |
||||
{{ scope.row.action }} |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="备注" align="center"> |
||||
<template slot-scope="scope"> |
||||
{{ scope.row.description }} |
||||
</template> |
||||
</el-table-column> |
||||
|
||||
<el-table-column align="center" prop="created_time" label="创建时间" width="120"> |
||||
<template slot-scope="scope"> |
||||
<i class="el-icon-time" /> |
||||
<el-tooltip :content="scope.row.created_time"> |
||||
<span>{{ scope.row.created_time|formatTime }}</span> |
||||
</el-tooltip> |
||||
</template> |
||||
</el-table-column> |
||||
|
||||
<el-table-column label="操作" align="center" width="160" class-name="small-padding fixed-width"> |
||||
<template slot-scope="scope"> |
||||
<el-button type="danger" size="mini" @click="delbill(scope.row.id)"> |
||||
删除 |
||||
</el-button> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
<pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" @pagination="fetchData" /> |
||||
|
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import Pagination from '@/components/Pagination' // secondary package based on el-pagination |
||||
import waves from '@/directive/waves' |
||||
import { delBillInfo, getBillList } from '@/api/developer' |
||||
|
||||
const sortOptions = [ |
||||
{ label: '创建时间 Ascending', key: 'created_time' }, |
||||
{ label: '创建时间 Descending', key: '-created_time' } |
||||
] |
||||
|
||||
export default { |
||||
name: 'BillInfo', |
||||
components: { Pagination }, |
||||
directives: { waves }, |
||||
filters: { |
||||
formatTime(time) { |
||||
return time.split('T')[0] |
||||
}, |
||||
certStatusFilter(status) { |
||||
const statusMap = { |
||||
'0': 'danger', |
||||
'1': 'success', |
||||
'2': 'gray', |
||||
'3': 'info' |
||||
} |
||||
return statusMap[status] |
||||
}, |
||||
certLableFilter(row) { |
||||
for (const v of row.auth_type_choices) { |
||||
if (v.id === row.auth_type) { |
||||
return v.name |
||||
} |
||||
} |
||||
}, |
||||
statusFilter(status) { |
||||
const statusMap = { |
||||
true: 'success', |
||||
false: 'danger' |
||||
} |
||||
return statusMap[status] |
||||
}, |
||||
appStatusNameFilter(row) { |
||||
for (const r of row.status_choices) { |
||||
if (r.id === row.status) { |
||||
return r.name |
||||
} |
||||
} |
||||
}, |
||||
appStatusFilter(status) { |
||||
const statusMap = { |
||||
'0': 'danger', |
||||
'1': 'success', |
||||
'2': 'gray' |
||||
} |
||||
return statusMap[status] |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
list: null, |
||||
listLoading: true, |
||||
total: 0, |
||||
listQuery: { |
||||
page: 1, |
||||
limit: 10, |
||||
ordering: '-created_time', |
||||
action: undefined, |
||||
app_id: undefined, |
||||
to_user_id: undefined, |
||||
user_id: undefined, |
||||
udid: undefined |
||||
}, |
||||
action_choices: undefined, |
||||
sortOptions |
||||
} |
||||
}, |
||||
created() { |
||||
this.listQuery.issuer_id = this.$route.params && this.$route.params.issuer_id |
||||
this.listQuery.user_id = this.$route.params && this.$route.params.user_id |
||||
this.fetchData() |
||||
}, |
||||
methods: { |
||||
handleFilter() { |
||||
this.listQuery.page = 1 |
||||
this.fetchData() |
||||
}, |
||||
delbill(id) { |
||||
delBillInfo(id).then(response => { |
||||
this.$message.success('删除成功') |
||||
this.fetchData() |
||||
this.listLoading = false |
||||
}) |
||||
}, |
||||
fetchData() { |
||||
this.listLoading = true |
||||
getBillList(this.listQuery).then(response => { |
||||
this.list = response.data.results |
||||
if (this.list && this.list.length > 0) { |
||||
this.action_choices = this.list[0].action_choices |
||||
} |
||||
this.total = response.data.count |
||||
this.listLoading = false |
||||
}) |
||||
} |
||||
} |
||||
} |
||||
</script> |
@ -0,0 +1,193 @@ |
||||
<template> |
||||
<div class="app-container"> |
||||
<el-form ref="postForm" :model="postForm" label-width="100px" :disabled="!is_edit"> |
||||
<el-row> |
||||
<el-col :span="12"> |
||||
<el-form-item label="用户ID"> |
||||
<el-row :gutter="12"> |
||||
<el-col :span="16"> |
||||
<el-input :value="postForm.user_id" disabled /> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
<el-form-item label="issuer_id"> |
||||
<el-row :gutter="12"> |
||||
<el-col :span="16"> |
||||
<el-input v-model="postForm.issuer_id" /> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
<el-form-item label="可使用设备数"> |
||||
<el-row :gutter="12"> |
||||
<el-col :span="16"> |
||||
<el-input-number v-model="postForm.usable_number" :min="0" :max="100" label="可使用设备数" /> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
<el-form-item label="已消耗设备数"> |
||||
<el-row :gutter="12"> |
||||
<el-col :span="16"> |
||||
<el-input-number v-model="postForm.use_number" :min="0" :max="100" label="已消耗设备数" /> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
<el-form-item label="账户类型"> |
||||
<el-row :gutter="12"> |
||||
<el-col :span="16"> |
||||
<el-select v-model="postForm.auth_type" class="filter-item" disabled> |
||||
<el-option v-for="item in postForm.auth_type_choices" :key="item.id" :label="item.name" :value="item.id" /> |
||||
</el-select> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
<el-form-item label="创建时间" prop="timestamp"> |
||||
<el-row :gutter="20"> |
||||
<el-col :span="8"> |
||||
<el-date-picker :value="postForm.created_time" type="datetime" disabled /> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
<el-form-item label="更新时间" prop="timestamp"> |
||||
<el-row :gutter="20"> |
||||
<el-col :span="8"> |
||||
<el-date-picker :value="postForm.updated_time" type="datetime" disabled /> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
<el-form-item label="描述信息"> |
||||
<el-row :gutter="12"> |
||||
<el-col :span="16"> |
||||
<el-input v-model="postForm.description" :autosize="{ minRows: 4, maxRows: 6}" type="textarea" /> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
</el-col> |
||||
<el-col :span="12"> |
||||
<el-form-item label="账户状态" label-width="160px"> |
||||
<el-row :gutter="12"> |
||||
<el-col :span="16"> |
||||
<el-tooltip :content="postForm.is_actived|userStatusFilter" placement="top"> |
||||
<el-switch |
||||
v-model="postForm.is_actived" |
||||
active-color="#13ce66" |
||||
inactive-color="#ff4949" |
||||
:active-value="true" |
||||
:inactive-value="false" |
||||
/> |
||||
</el-tooltip> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
<el-form-item label="证书过期时间" prop="timestamp" label-width="160px"> |
||||
<el-row :gutter="20"> |
||||
<el-col :span="8"> |
||||
<el-date-picker :value="postForm.cert_expire_time" type="datetime" disabled /> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
<el-form-item label="private_key_id" label-width="160px"> |
||||
<el-row :gutter="12"> |
||||
<el-col :span="16"> |
||||
<el-input v-model="postForm.private_key_id" /> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
<el-form-item label="p8key" label-width="160px"> |
||||
<el-row :gutter="12"> |
||||
<el-col :span="16"> |
||||
<el-input v-model="postForm.p8key" :autosize="{ minRows: 4, maxRows: 6}" type="textarea" /> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
<el-form-item label="certid" label-width="160px"> |
||||
<el-row :gutter="12"> |
||||
<el-col :span="16"> |
||||
<el-input v-model="postForm.certid" /> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form> |
||||
<el-col :span="9" style="float: right"> |
||||
<el-button v-if="!is_edit" type="primary" @click="is_edit=true">修改</el-button> |
||||
<div v-else> |
||||
<el-button type="primary" @click="is_edit=false">取消</el-button> |
||||
<el-button type="primary" @click="updateData">保存修改</el-button> |
||||
</div> |
||||
</el-col> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import { getDeveloperInfo, updatedeveloperInfo } from '@/api/developer' |
||||
|
||||
const defaultForm = { |
||||
user_id: undefined, |
||||
is_actived: undefined, |
||||
issuer_id: undefined, |
||||
private_key_id: undefined, |
||||
p8key: undefined, |
||||
certid: undefined, |
||||
created_time: undefined, |
||||
description: undefined, |
||||
usable_number: undefined, |
||||
use_number: undefined, |
||||
auth_type: undefined, |
||||
cert_expire_time: undefined, |
||||
updated_time: undefined, |
||||
auth_type_choices: [] |
||||
} |
||||
|
||||
export default { |
||||
name: 'DeveloperDetail', |
||||
components: { }, filters: { |
||||
userStatusFilter(status) { |
||||
const statusMap = { |
||||
true: '激活,允许使用', |
||||
false: '禁用,禁止使用' |
||||
} |
||||
return statusMap[status] |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
postForm: Object.assign({}, defaultForm), |
||||
loading: false, |
||||
is_edit: false, |
||||
id: '' |
||||
} |
||||
}, |
||||
computed: {}, |
||||
created() { |
||||
this.id = this.$route.params && this.$route.params.id |
||||
this.fetchData(this.id) |
||||
}, |
||||
methods: { |
||||
fetchData(id) { |
||||
getDeveloperInfo(id).then(response => { |
||||
if (response.data) { |
||||
this.postForm = response.data |
||||
} |
||||
}).catch(err => { |
||||
console.log(err) |
||||
}) |
||||
}, |
||||
updateData() { |
||||
updatedeveloperInfo(this.id, this.postForm).then(response => { |
||||
this.$message.success('更新成功') |
||||
this.postForm = response.data |
||||
}).catch(err => { |
||||
console.log(err) |
||||
}) |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style scoped> |
||||
.editor-container { |
||||
position: relative; |
||||
height: 100%; |
||||
} |
||||
</style> |
@ -0,0 +1,218 @@ |
||||
<template> |
||||
<div class="app-container"> |
||||
<div class="filter-container"> |
||||
<el-input v-model="listQuery.user_id" placeholder="用户ID" style="width: 140px;" class="filter-item" clearable @keyup.enter.native="handleFilter" /> |
||||
<el-input v-model="listQuery.issuer_id" placeholder="issuer_id" style="width: 300px;" class="filter-item" clearable @keyup.enter.native="handleFilter" /> |
||||
<el-input v-model="listQuery.private_key_id" placeholder="private_key_id" style="width: 200px;" class="filter-item" clearable @keyup.enter.native="handleFilter" /> |
||||
<el-input v-model="listQuery.certid" placeholder="证书ID" style="width: 200px;" class="filter-item" clearable @keyup.enter.native="handleFilter" /> |
||||
<el-input v-model="listQuery.description" placeholder="备注" style="width: 200px;" class="filter-item" clearable @keyup.enter.native="handleFilter" /> |
||||
<el-select v-model="listQuery.auth_type" placeholder="账户类型" clearable class="filter-item" style="width: 140px" @change="handleFilter"> |
||||
<el-option v-for="item in auth_type_choices" :key="item.id" :label="item.name" :value="item.id" /> |
||||
</el-select> |
||||
<el-select v-model="listQuery.ordering" style="width: 140px" class="filter-item" @change="handleFilter"> |
||||
<el-option v-for="item in sortOptions" :key="item.key" :label="item.label" :value="item.key" /> |
||||
</el-select> |
||||
<el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter"> |
||||
Search |
||||
</el-button> |
||||
</div> |
||||
<el-table |
||||
v-loading="listLoading" |
||||
:data="list" |
||||
element-loading-text="Loading" |
||||
border |
||||
fit |
||||
highlight-current-row |
||||
stripe |
||||
> |
||||
<el-table-column align="center" label="ID" width="90"> |
||||
<template slot-scope="scope"> |
||||
{{ scope.row.id }} |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="用户ID" width="100" align="center"> |
||||
<template slot-scope="scope"> |
||||
<router-link :to="{name: 'user_info_edit',params:{id:scope.row.user_id}}"> |
||||
<el-link type="primary"> {{ scope.row.user_id }}</el-link> |
||||
</router-link> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="issuer_id" width="300"> |
||||
<template slot-scope="scope"> |
||||
{{ scope.row.issuer_id }} |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="private_key_id" align="center"> |
||||
<template slot-scope="scope"> |
||||
<span>{{ scope.row.private_key_id }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="certid" align="center"> |
||||
<template slot-scope="scope"> |
||||
{{ scope.row.certid }} |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="可用设备数" align="center" width="100"> |
||||
<template slot-scope="scope"> |
||||
{{ scope.row.usable_number }} |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="消耗设备数" align="center" width="100"> |
||||
<template slot-scope="scope"> |
||||
<router-link :to="{name: 'devices_info_list',params:{issuer_id:scope.row.issuer_id}}"> |
||||
<el-link type="primary"> {{ scope.row.use_number }}</el-link> |
||||
</router-link> |
||||
</template> |
||||
</el-table-column> |
||||
|
||||
<el-table-column class-name="status-col" label="账户类型" width="130" align="center"> |
||||
<template slot-scope="scope"> |
||||
<el-tag :type="scope.row.auth_type | certStatusFilter">{{ scope.row| certLableFilter }}</el-tag> |
||||
</template> |
||||
</el-table-column> |
||||
|
||||
<el-table-column class-name="status-col" label="是否激活" width="80" align="center"> |
||||
<template slot-scope="scope"> |
||||
<el-tag :type="scope.row.is_actived | statusFilter">{{ scope.row |StatusNameFilter }}</el-tag> |
||||
</template> |
||||
</el-table-column> |
||||
|
||||
<el-table-column align="center" prop="created_time" label="创建时间" width="120"> |
||||
<template slot-scope="scope"> |
||||
<i class="el-icon-time" /> |
||||
<el-tooltip :content="scope.row.created_time"> |
||||
<span>{{ scope.row.created_time|formatTime }}</span> |
||||
</el-tooltip> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column align="center" prop="created_time" label="证书过期时间" width="120"> |
||||
<template slot-scope="scope"> |
||||
<i class="el-icon-time" /> |
||||
<el-tooltip :content="scope.row.updated_time"> |
||||
<span>{{ scope.row.cert_expire_time|formatTime }}</span> |
||||
</el-tooltip> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="操作" align="center" width="160" class-name="small-padding fixed-width"> |
||||
<template slot-scope="scope"> |
||||
<router-link :to="{name: 'developer_user_info_edit',params:{id:scope.row.id}}"> |
||||
<el-button type="primary" size="mini"> |
||||
查看编辑 |
||||
</el-button> |
||||
</router-link> |
||||
<!-- <el-button type="danger" size="mini" @click="deleteApp(scope.row.id)">--> |
||||
<!-- 删除--> |
||||
<!-- </el-button>--> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
<pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" @pagination="fetchData" /> |
||||
|
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import { getDeveloperList } from '@/api/developer' |
||||
import Pagination from '@/components/Pagination' // secondary package based on el-pagination |
||||
import waves from '@/directive/waves' // waves directive |
||||
|
||||
const sortOptions = [ |
||||
{ label: '创建时间 Ascending', key: 'created_time' }, |
||||
{ label: '创建时间 Descending', key: '-created_time' }, |
||||
{ label: '更新时间 Ascending', key: 'updated_time' }, |
||||
{ label: '更新时间 Descending', key: '-updated_time' }, |
||||
{ label: '证书过期时间 Ascending', key: 'cert_expire_time' }, |
||||
{ label: '证书过期时间 Descending', key: '-cert_expire_time' } |
||||
] |
||||
|
||||
export default { |
||||
name: 'StorageInfo', |
||||
components: { Pagination }, |
||||
directives: { waves }, |
||||
filters: { |
||||
formatTime(time) { |
||||
return time.split('T')[0] |
||||
}, |
||||
certStatusFilter(status) { |
||||
const statusMap = { |
||||
'0': 'danger', |
||||
'1': 'success', |
||||
'2': 'gray', |
||||
'3': 'info' |
||||
} |
||||
return statusMap[status] |
||||
}, |
||||
certLableFilter(row) { |
||||
for (const v of row.auth_type_choices) { |
||||
if (v.id === row.auth_type) { |
||||
return v.name |
||||
} |
||||
} |
||||
}, |
||||
statusFilter(status) { |
||||
const statusMap = { |
||||
true: 'success', |
||||
false: 'danger' |
||||
} |
||||
return statusMap[status] |
||||
}, |
||||
StatusNameFilter(row) { |
||||
for (const r of row.status_choices) { |
||||
if (r.id === row.status) { |
||||
return r.name |
||||
} |
||||
} |
||||
}, |
||||
appStatusFilter(status) { |
||||
const statusMap = { |
||||
'0': 'danger', |
||||
'1': 'success', |
||||
'2': 'gray' |
||||
} |
||||
return statusMap[status] |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
list: null, |
||||
listLoading: true, |
||||
total: 0, |
||||
listQuery: { |
||||
page: 1, |
||||
limit: 10, |
||||
ordering: '-created_time', |
||||
issuer_id: undefined, |
||||
private_key_id: undefined, |
||||
certid: undefined, |
||||
description: undefined, |
||||
user_id: undefined, |
||||
auth_type: undefined |
||||
}, |
||||
sortOptions, |
||||
auth_type_choices: [], |
||||
status_choices: [] |
||||
} |
||||
}, |
||||
created() { |
||||
this.fetchData() |
||||
}, |
||||
methods: { |
||||
handleFilter() { |
||||
this.listQuery.page = 1 |
||||
this.fetchData() |
||||
}, |
||||
fetchData() { |
||||
this.listLoading = true |
||||
getDeveloperList(this.listQuery).then(response => { |
||||
this.list = response.data.results |
||||
if (this.list && this.list.length > 0) { |
||||
this.auth_type_choices = this.list[0].auth_type_choices |
||||
this.status_choices = this.list[0].status_choices |
||||
} |
||||
this.total = response.data.count |
||||
this.listLoading = false |
||||
}) |
||||
} |
||||
} |
||||
} |
||||
</script> |
@ -0,0 +1,3 @@ |
||||
<template> |
||||
<router-view /> |
||||
</template> |
@ -0,0 +1,157 @@ |
||||
<template> |
||||
<div class="app-container"> |
||||
<el-form ref="postForm" :model="postForm" label-width="100px" :disabled="!is_edit"> |
||||
<el-row> |
||||
<el-col :span="12"> |
||||
<el-form-item label="用户ID"> |
||||
<el-row :gutter="12"> |
||||
<el-col :span="16"> |
||||
<el-input :value="postForm.user_id" disabled /> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
<el-form-item label="微信openid"> |
||||
<el-row :gutter="12"> |
||||
<el-col :span="16"> |
||||
<el-input v-model="postForm.openid" disabled /> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
|
||||
<el-form-item label="微信昵称"> |
||||
<el-row :gutter="12"> |
||||
<el-col :span="16"> |
||||
<el-input v-model="postForm.nickname" /> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
|
||||
<el-form-item label="创建时间" prop="timestamp"> |
||||
<el-row :gutter="20"> |
||||
<el-col :span="8"> |
||||
<el-date-picker :value="postForm.created_time" disabled type="datetime" /> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
<el-form-item label="订阅时间" prop="timestamp"> |
||||
<el-row :gutter="20"> |
||||
<el-col :span="8"> |
||||
<el-date-picker :value="postForm.subscribe_time*1000" disabled type="datetime" /> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
</el-col> |
||||
<el-col :span="12"> |
||||
<el-form-item label="用户头像" label-width="160px"> |
||||
<el-row :gutter="12"> |
||||
<el-col :span="16"> |
||||
<el-image |
||||
:preview-src-list="[postForm.head_img_url]" |
||||
:src="postForm.head_img_url" |
||||
fit="contain" |
||||
style="width: 100px; height: 100px" |
||||
/> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
<el-form-item label="扫码登录" label-width="160px"> |
||||
<el-row :gutter="12"> |
||||
<el-col :span="16"> |
||||
<el-input v-model="postForm.enable_login" disabled /> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
<el-form-item label="消息通知" label-width="160px"> |
||||
<el-row :gutter="12"> |
||||
<el-col :span="16"> |
||||
<el-input v-model="postForm.enable_notify" disabled /> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
<el-form-item label="订阅状态" label-width="160px"> |
||||
<el-row :gutter="12"> |
||||
<el-col :span="16"> |
||||
<el-select v-model="postForm.subscribe" class="filter-item" disabled> |
||||
<el-option v-for="item in wxbind_state_choices" :key="item.id" :label="item.name" :value="item.id" /> |
||||
</el-select> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
|
||||
</el-col> |
||||
</el-row> |
||||
</el-form> |
||||
<el-col :span="9" style="float: right"> |
||||
<el-button v-if="!is_edit" type="primary" :disabled="postForm.id === postForm.used_id" @click="is_edit=true">修改</el-button> |
||||
<div v-else> |
||||
<el-button type="primary" @click="is_edit=false">取消</el-button> |
||||
<el-button type="primary" @click="updateData">保存修改</el-button> |
||||
</div> |
||||
</el-col> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import { getWxBindInfos, updateWxBindInfo } from '@/api/wxbind' |
||||
|
||||
const wxbind_state_choices = [ |
||||
{ id: false, name: '未订阅' }, |
||||
{ id: true, name: '已订阅' } |
||||
] |
||||
|
||||
const defaultForm = { |
||||
user_id: undefined, |
||||
address: undefined, |
||||
created_time: undefined, |
||||
head_img_url: undefined, |
||||
id: undefined, |
||||
nickname: undefined, |
||||
openid: undefined, |
||||
subscribe: undefined, |
||||
subscribe_time: undefined, |
||||
enable_login: undefined, |
||||
enable_notify: undefined |
||||
} |
||||
|
||||
export default { |
||||
name: 'OrderDetail', |
||||
components: { }, filters: {}, |
||||
data() { |
||||
return { |
||||
postForm: Object.assign({}, defaultForm), |
||||
loading: false, |
||||
is_edit: false, |
||||
wxbind_state_choices, |
||||
id: '' |
||||
} |
||||
}, |
||||
computed: {}, |
||||
created() { |
||||
this.id = this.$route.params && this.$route.params.id |
||||
this.fetchData(this.id) |
||||
}, |
||||
methods: { |
||||
fetchData(id) { |
||||
getWxBindInfos(id).then(response => { |
||||
if (response.data) { |
||||
this.postForm = response.data |
||||
} |
||||
}).catch(err => { |
||||
console.log(err) |
||||
}) |
||||
}, |
||||
updateData() { |
||||
updateWxBindInfo(this.id, this.postForm).then(response => { |
||||
this.$message.success('更新成功') |
||||
this.postForm = response.data |
||||
}).catch(err => { |
||||
console.log(err) |
||||
}) |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style scoped> |
||||
|
||||
</style> |
@ -0,0 +1,192 @@ |
||||
<template> |
||||
<div class="app-container"> |
||||
<div class="filter-container"> |
||||
<el-input v-model="listQuery.user_id" placeholder="用户ID" style="width: 140px;" class="filter-item" clearable @keyup.enter.native="handleFilter" /> |
||||
<el-input v-model="listQuery.openid" placeholder="微信openid" style="width: 300px;" class="filter-item" clearable @keyup.enter.native="handleFilter" /> |
||||
<el-input v-model="listQuery.nickname" placeholder="微信昵称" style="width: 200px;" class="filter-item" clearable @keyup.enter.native="handleFilter" /> |
||||
<el-select v-model="listQuery.subscribe" placeholder="玩家是否订阅" clearable class="filter-item" style="width: 140px" @change="handleFilter"> |
||||
<el-option v-for="item in wxbind_state_choices" :key="item.id" :label="item.name" :value="item.id" /> |
||||
</el-select> |
||||
<el-select v-model="listQuery.ordering" style="width: 140px" class="filter-item" @change="handleFilter"> |
||||
<el-option v-for="item in sortOptions" :key="item.key" :label="item.label" :value="item.key" /> |
||||
</el-select> |
||||
<el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter"> |
||||
Search |
||||
</el-button> |
||||
</div> |
||||
<el-table |
||||
v-loading="listLoading" |
||||
:data="list" |
||||
element-loading-text="Loading" |
||||
border |
||||
fit |
||||
highlight-current-row |
||||
stripe |
||||
> |
||||
<el-table-column align="center" label="ID" width="90"> |
||||
<template slot-scope="scope"> |
||||
{{ scope.row.id }} |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="用户ID" width="100" align="center"> |
||||
<template slot-scope="scope"> |
||||
<router-link :to="{name: 'user_info_edit',params:{id:scope.row.user_id}}"> |
||||
<el-link type="primary"> {{ scope.row.user_id }}</el-link> |
||||
</router-link> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="头像" align="center"> |
||||
<template slot-scope="scope"> |
||||
<el-image :src="scope.row.head_img_url" :preview-src-list="[scope.row.head_img_url]" fit="contain" style="width: 80px; height: 80px" /> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="微信昵称" min-width="180px" align="center"> |
||||
<template slot-scope="scope"> |
||||
{{ scope.row.nickname }} |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="微信openid" min-width="280px" align="center"> |
||||
<template slot-scope="scope"> |
||||
{{ scope.row.openid }} |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="允许扫码登录" min-width="100px" align="center"> |
||||
<template slot-scope="scope"> |
||||
{{ scope.row.enable_login }} |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="允许消息通知" min-width="100px" align="center"> |
||||
<template slot-scope="scope"> |
||||
{{ scope.row.enable_notify }} |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column class-name="status-col" label="订阅状态" width="95" align="center"> |
||||
<template slot-scope="scope"> |
||||
<el-tag :type="scope.row.subscribe | statusFilter">{{ scope.row| statusLableFilter }}</el-tag> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column align="center" prop="created_time" label="创建时间" width="120"> |
||||
<template slot-scope="scope"> |
||||
<i class="el-icon-time" /> |
||||
<el-tooltip :content="scope.row.created_time"> |
||||
<span>{{ scope.row.created_time|formatTime }}</span> |
||||
</el-tooltip> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="操作" align="center" width="160" class-name="small-padding fixed-width"> |
||||
<template slot-scope="scope"> |
||||
<router-link :to="{name: 'wxbind_info_edit',params:{id:scope.row.id}}"> |
||||
<el-button type="primary" size="mini"> |
||||
查看编辑 |
||||
</el-button> |
||||
</router-link> |
||||
<el-button type="danger" size="mini" @click="remove_wxbind(scope.row.id)"> |
||||
删除 |
||||
</el-button> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
<pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" @pagination="fetchData" /> |
||||
|
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import { deleteWxBind, getWxBindList } from '@/api/wxbind' |
||||
import { baseFilter } from '@/utils' |
||||
import Pagination from '@/components/Pagination' // secondary package based on el-pagination |
||||
import waves from '@/directive/waves' // waves directive |
||||
|
||||
const sortOptions = [ |
||||
{ label: '创建时间 Ascending', key: 'created_time' }, |
||||
{ label: '创建时间 Descending', key: '-created_time' } |
||||
] |
||||
|
||||
const wxbind_state_choices = [ |
||||
{ id: false, name: '未订阅' }, |
||||
{ id: true, name: '已订阅' } |
||||
] |
||||
|
||||
export default { |
||||
name: 'WxBindInfo', |
||||
components: { Pagination }, |
||||
directives: { waves }, |
||||
filters: { |
||||
formatTime(time) { |
||||
if (time) { |
||||
return time.split('T')[0] |
||||
} |
||||
}, |
||||
wxbindStatusFilter(status) { |
||||
const statusMap = { |
||||
'1': 'success', |
||||
'0': 'gray', |
||||
'2': 'info' } |
||||
return statusMap[status] |
||||
}, |
||||
wxbindLableFilter(row) { |
||||
if (row.wxbind_type === 2) { |
||||
return '应用' + row.app_info.name + '域名' |
||||
} |
||||
return baseFilter(row.wxbind_type, row.wxbind_type_choices) |
||||
}, |
||||
statusLableFilter(row) { |
||||
return baseFilter(row.subscribe, wxbind_state_choices) |
||||
}, |
||||
statusFilter(status) { |
||||
const statusMap = { |
||||
true: 'success', |
||||
false: 'danger' |
||||
} |
||||
return statusMap[status] |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
list: null, |
||||
listLoading: true, |
||||
total: 0, |
||||
listQuery: { |
||||
page: 1, |
||||
limit: 10, |
||||
user_id: undefined, |
||||
ordering: '-created_time', |
||||
openid: undefined, |
||||
nickname: undefined, |
||||
subscribe: undefined |
||||
}, |
||||
sortOptions, |
||||
wxbind_state_choices |
||||
} |
||||
}, |
||||
created() { |
||||
this.fetchData() |
||||
}, mounted() { |
||||
if (this.$route.params.user_id) { |
||||
this.listQuery.user_id = this.$route.params.user_id |
||||
} |
||||
console.log(this.$router) |
||||
}, |
||||
methods: { |
||||
remove_wxbind(wxbind_id) { |
||||
deleteWxBind(wxbind_id).then(response => { |
||||
this.list = response.data |
||||
this.total = response.total |
||||
this.listLoading = false |
||||
}) |
||||
}, |
||||
handleFilter() { |
||||
this.listQuery.page = 1 |
||||
this.fetchData() |
||||
}, |
||||
fetchData() { |
||||
this.listLoading = true |
||||
getWxBindList(this.listQuery).then(response => { |
||||
this.list = response.data.results |
||||
this.total = response.data.count |
||||
this.listLoading = false |
||||
}) |
||||
} |
||||
} |
||||
} |
||||
</script> |
@ -1,16 +0,0 @@ |
||||
window.g = { |
||||
baseUrl: 'https://app.hehelucky.cn', |
||||
PaymentQuestionMsg:'如对充值订单有疑问,请联系 nineven@qq.com', |
||||
footer: { |
||||
copyright: 'Copyright © 2017-2020 第九系艾文 版权所有.', |
||||
ipcBeiAn: { |
||||
url: 'https://beian.miit.gov.cn', |
||||
text: '豫ICP备15004336号-3', |
||||
}, |
||||
gongAnBeiAn: { |
||||
url: 'http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=41142202000049', |
||||
text: '豫公网安备 41142202000049号', |
||||
}, |
||||
} |
||||
|
||||
}; |
After Width: | Height: | Size: 1.7 KiB |
@ -1,87 +1,87 @@ |
||||
<template> |
||||
<div id="app" ref="app"> |
||||
<router-view></router-view> |
||||
</div> |
||||
<div id="app" ref="app"> |
||||
<router-view/> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
|
||||
export default { |
||||
name: 'app', |
||||
data() { |
||||
return {} |
||||
}, |
||||
} |
||||
export default { |
||||
name: 'app', |
||||
data() { |
||||
return {} |
||||
}, |
||||
} |
||||
</script> |
||||
|
||||
<style> |
||||
body { |
||||
background-color: #F6F6F6; |
||||
} |
||||
|
||||
html, body { |
||||
height: 100%; |
||||
} |
||||
|
||||
@font-face { |
||||
font-family: "iconfont"; |
||||
src: url('./assets/icon/iconfont.eot?t=1583637102320'); /* IE9 */ |
||||
src: url('./assets/icon/iconfont.eot?t=1583637102320#iefix') format('embedded-opentype'), /* IE6-IE8 */ url('data:application/x-font-woff2;charset=utf-8;base64,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') format('woff2'), |
||||
url('./assets/icon/iconfont.woff?t=1583637102320') format('woff'), |
||||
url('./assets/icon/iconfont.ttf?t=1583637102320') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */ url('./assets/icon/iconfont.svg?t=1583637102320#iconfont') format('svg'); /* iOS 4.1- */ |
||||
} |
||||
|
||||
.iconfont { |
||||
font-family: "iconfont" !important; |
||||
font-size: 16px; |
||||
font-style: normal; |
||||
-webkit-font-smoothing: antialiased; |
||||
-moz-osx-font-smoothing: grayscale; |
||||
} |
||||
|
||||
.icon-android:before { |
||||
content: "\e61d"; |
||||
} |
||||
|
||||
.icon-android1:before { |
||||
content: "\e616"; |
||||
} |
||||
|
||||
.icon-android2:before { |
||||
content: "\e62a"; |
||||
} |
||||
|
||||
.icon-ios:before { |
||||
content: "\e60c"; |
||||
} |
||||
|
||||
.icon-IOS:before { |
||||
content: "\e68c"; |
||||
} |
||||
|
||||
.icon-ios1:before { |
||||
content: "\e601"; |
||||
} |
||||
|
||||
.icon-ios2:before { |
||||
content: "\e64b"; |
||||
} |
||||
|
||||
.icon-Android:before { |
||||
content: "\e6d4"; |
||||
} |
||||
|
||||
.icon-android3:before { |
||||
content: "\e625"; |
||||
} |
||||
|
||||
.canvas { |
||||
position: fixed; |
||||
left: -0px; |
||||
top: 58px; |
||||
height: 100%; |
||||
z-index: -2; |
||||
width: 100%; |
||||
} |
||||
body { |
||||
background-color: #F6F6F6; |
||||
} |
||||
|
||||
html, body { |
||||
height: 100%; |
||||
} |
||||
|
||||
@font-face { |
||||
font-family: "iconfont"; |
||||
src: url('./assets/icon/iconfont.eot?t=1583637102320'); /* IE9 */ |
||||
src: url('./assets/icon/iconfont.eot?t=1583637102320#iefix') format('embedded-opentype'), /* IE6-IE8 */ url('data:application/x-font-woff2;charset=utf-8;base64,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') format('woff2'), |
||||
url('./assets/icon/iconfont.woff?t=1583637102320') format('woff'), |
||||
url('./assets/icon/iconfont.ttf?t=1583637102320') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */ url('./assets/icon/iconfont.svg?t=1583637102320#iconfont') format('svg'); /* iOS 4.1- */ |
||||
} |
||||
|
||||
.iconfont { |
||||
font-family: "iconfont" !important; |
||||
font-size: 16px; |
||||
font-style: normal; |
||||
-webkit-font-smoothing: antialiased; |
||||
-moz-osx-font-smoothing: grayscale; |
||||
} |
||||
|
||||
.icon-android:before { |
||||
content: "\e61d"; |
||||
} |
||||
|
||||
.icon-android1:before { |
||||
content: "\e616"; |
||||
} |
||||
|
||||
.icon-android2:before { |
||||
content: "\e62a"; |
||||
} |
||||
|
||||
.icon-ios:before { |
||||
content: "\e60c"; |
||||
} |
||||
|
||||
.icon-IOS:before { |
||||
content: "\e68c"; |
||||
} |
||||
|
||||
.icon-ios1:before { |
||||
content: "\e601"; |
||||
} |
||||
|
||||
.icon-ios2:before { |
||||
content: "\e64b"; |
||||
} |
||||
|
||||
.icon-Android:before { |
||||
content: "\e6d4"; |
||||
} |
||||
|
||||
.icon-android3:before { |
||||
content: "\e625"; |
||||
} |
||||
|
||||
.canvas { |
||||
position: fixed; |
||||
left: -0px; |
||||
top: 58px; |
||||
height: 100%; |
||||
z-index: -2; |
||||
width: 100%; |
||||
} |
||||
|
||||
</style> |
||||
|
@ -1,75 +1,75 @@ |
||||
<template> |
||||
<div id="download" ref="download"> |
||||
<router-view></router-view> |
||||
</div> |
||||
<div id="download" ref="download"> |
||||
<router-view></router-view> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
|
||||
export default { |
||||
name: 'download', |
||||
data() { |
||||
return {} |
||||
}, |
||||
} |
||||
export default { |
||||
name: 'download', |
||||
data() { |
||||
return {} |
||||
}, |
||||
} |
||||
</script> |
||||
|
||||
<style> |
||||
body { |
||||
background-color: #F6F6F6; |
||||
} |
||||
|
||||
@font-face { |
||||
font-family: "iconfont"; |
||||
src: url('./assets/icon/iconfont.eot?t=1583637102320'); /* IE9 */ |
||||
src: url('./assets/icon/iconfont.eot?t=1583637102320#iefix') format('embedded-opentype'), /* IE6-IE8 */ url('data:application/x-font-woff2;charset=utf-8;base64,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') format('woff2'), |
||||
url('./assets/icon/iconfont.woff?t=1583637102320') format('woff'), |
||||
url('./assets/icon/iconfont.ttf?t=1583637102320') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */ url('./assets/icon/iconfont.svg?t=1583637102320#iconfont') format('svg'); /* iOS 4.1- */ |
||||
} |
||||
|
||||
.iconfont { |
||||
font-family: "iconfont" !important; |
||||
font-size: 16px; |
||||
font-style: normal; |
||||
-webkit-font-smoothing: antialiased; |
||||
-moz-osx-font-smoothing: grayscale; |
||||
} |
||||
|
||||
.icon-android:before { |
||||
content: "\e61d"; |
||||
} |
||||
|
||||
.icon-android1:before { |
||||
content: "\e616"; |
||||
} |
||||
|
||||
.icon-android2:before { |
||||
content: "\e62a"; |
||||
} |
||||
|
||||
.icon-ios:before { |
||||
content: "\e60c"; |
||||
} |
||||
|
||||
.icon-IOS:before { |
||||
content: "\e68c"; |
||||
} |
||||
|
||||
.icon-ios1:before { |
||||
content: "\e601"; |
||||
} |
||||
|
||||
.icon-ios2:before { |
||||
content: "\e64b"; |
||||
} |
||||
|
||||
.icon-Android:before { |
||||
content: "\e6d4"; |
||||
} |
||||
|
||||
.icon-android3:before { |
||||
content: "\e625"; |
||||
} |
||||
body { |
||||
background-color: #F6F6F6; |
||||
} |
||||
|
||||
@font-face { |
||||
font-family: "iconfont"; |
||||
src: url('./assets/icon/iconfont.eot?t=1583637102320'); /* IE9 */ |
||||
src: url('./assets/icon/iconfont.eot?t=1583637102320#iefix') format('embedded-opentype'), /* IE6-IE8 */ url('data:application/x-font-woff2;charset=utf-8;base64,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') format('woff2'), |
||||
url('./assets/icon/iconfont.woff?t=1583637102320') format('woff'), |
||||
url('./assets/icon/iconfont.ttf?t=1583637102320') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */ url('./assets/icon/iconfont.svg?t=1583637102320#iconfont') format('svg'); /* iOS 4.1- */ |
||||
} |
||||
|
||||
.iconfont { |
||||
font-family: "iconfont" !important; |
||||
font-size: 16px; |
||||
font-style: normal; |
||||
-webkit-font-smoothing: antialiased; |
||||
-moz-osx-font-smoothing: grayscale; |
||||
} |
||||
|
||||
.icon-android:before { |
||||
content: "\e61d"; |
||||
} |
||||
|
||||
.icon-android1:before { |
||||
content: "\e616"; |
||||
} |
||||
|
||||
.icon-android2:before { |
||||
content: "\e62a"; |
||||
} |
||||
|
||||
.icon-ios:before { |
||||
content: "\e60c"; |
||||
} |
||||
|
||||
.icon-IOS:before { |
||||
content: "\e68c"; |
||||
} |
||||
|
||||
.icon-ios1:before { |
||||
content: "\e601"; |
||||
} |
||||
|
||||
.icon-ios2:before { |
||||
content: "\e64b"; |
||||
} |
||||
|
||||
.icon-Android:before { |
||||
content: "\e6d4"; |
||||
} |
||||
|
||||
.icon-android3:before { |
||||
content: "\e625"; |
||||
} |
||||
|
||||
|
||||
</style> |
||||
|
After Width: | Height: | Size: 71 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 62 KiB |
After Width: | Height: | Size: 126 KiB |
After Width: | Height: | Size: 300 KiB |
After Width: | Height: | Size: 169 KiB |
After Width: | Height: | Size: 216 KiB |
After Width: | Height: | Size: 197 KiB |
@ -1,119 +1,132 @@ |
||||
<template> |
||||
<div ref="appbase"> |
||||
<el-dialog |
||||
title="绑定下载页域名" |
||||
:close-on-click-modal="false" |
||||
:close-on-press-escape="false" |
||||
:visible.sync="bind_domain_sure" |
||||
width="666px"> |
||||
<bind-domain transitionName="bind-user-domain"/> |
||||
</el-dialog> |
||||
<canvas ref="canvas" class="canvas" @mousemove="canvas_move" @mouseleave="canvas_leave"/> |
||||
<el-container> |
||||
<div style="margin: -5px 20px" v-if="$store.state.show_domain_msg"> |
||||
<el-alert |
||||
center |
||||
type="error" |
||||
:closable="false" |
||||
effect="dark"> |
||||
<div slot="title"> |
||||
<span :underline="false" |
||||
class="domian-tip-bar">应用分发请绑定您自己的域名,平台分发域名可能因不可违因素更换,将导致您的应用无法访问</span> |
||||
<el-button size="medium" @click="bind_domain_sure=true">立即绑定</el-button> |
||||
</div> |
||||
</el-alert> |
||||
</div> |
||||
<el-header> |
||||
<FirHeader/> |
||||
</el-header> |
||||
<div class="pbody"> |
||||
<router-view/> |
||||
</div> |
||||
<el-footer> |
||||
<el-divider/> |
||||
<FirFooter/> |
||||
</el-footer> |
||||
<el-tooltip placement="top" content="回到顶部"> |
||||
<back-to-top :custom-style="myBackToTopStyle" :visibility-height="300" :back-position="50" |
||||
transition-name="fade"/> |
||||
</el-tooltip> |
||||
</el-container> |
||||
</div> |
||||
<div ref="appbase"> |
||||
<el-dialog |
||||
:close-on-click-modal="false" |
||||
:close-on-press-escape="false" |
||||
:title="bind_domain_title" |
||||
:visible.sync="bind_domain_sure" |
||||
width="666px"> |
||||
<bind-domain v-if="bind_domain_sure" :domain_type="bind_domain_type" |
||||
:transitionName="`bind-user-domain`+ bind_domain_type"/> |
||||
</el-dialog> |
||||
<canvas ref="canvas" class="canvas" @mouseleave="canvas_leave" @mousemove="canvas_move"/> |
||||
<el-container> |
||||
<div v-if="$store.state.show_domain_msg" style="margin: -5px 20px"> |
||||
<el-alert |
||||
:closable="false" |
||||
center |
||||
effect="dark" |
||||
type="error"> |
||||
<div slot="title"> |
||||
<span class="domain-tip-bar">应用分发请绑定您自己的域名,平台分发域名可能因不可违因素更换,将导致您的应用无法访问</span> |
||||
<el-button size="small" @click="bind_domain_type=1,bind_domain_sure=true">立即绑定</el-button> |
||||
</div> |
||||
</el-alert> |
||||
</div> |
||||
<el-header> |
||||
<FirHeader/> |
||||
</el-header> |
||||
<div class="pbody"> |
||||
<router-view/> |
||||
</div> |
||||
<el-footer> |
||||
<el-divider/> |
||||
<FirFooter/> |
||||
</el-footer> |
||||
<el-tooltip content="回到顶部" placement="top"> |
||||
<back-to-top :back-position="50" :custom-style="myBackToTopStyle" :visibility-height="300" |
||||
transition-name="fade"/> |
||||
</el-tooltip> |
||||
</el-container> |
||||
</div> |
||||
|
||||
</template> |
||||
|
||||
<script> |
||||
import FirHeader from "@/components/FirHeader"; |
||||
import FirFooter from "@/components/FirFooter"; |
||||
import BackToTop from "@/components/base/BackToTop"; |
||||
import BindDomain from "@/components/base/BindDomain"; |
||||
import {show_beautpic,} from "@/utils"; |
||||
import FirHeader from "@/components/FirHeader"; |
||||
import FirFooter from "@/components/FirFooter"; |
||||
import BackToTop from "@/components/base/BackToTop"; |
||||
import BindDomain from "@/components/base/BindDomain"; |
||||
import {show_beautpic,} from "@/utils"; |
||||
|
||||
export default { |
||||
name: "FirBase", |
||||
components: {FirFooter, FirHeader, BackToTop, BindDomain}, |
||||
data() { |
||||
return { |
||||
mousePosition: {}, |
||||
bind_domain_sure: false, |
||||
active: 1, |
||||
domain_name: '', |
||||
bind_status: false, |
||||
domain_tData: [{'type': 'CNAME', 'host': 'xxx', 'dns': 'demo.xxx.cn'}], |
||||
myBackToTopStyle: { |
||||
right: '80px', |
||||
bottom: '100px', |
||||
width: '40px', |
||||
height: '40px', |
||||
'border-radius': '4px', |
||||
'line-height': '45px', |
||||
background: '#e7eaf1' |
||||
} |
||||
} |
||||
}, |
||||
mounted() { |
||||
let canvas = this.$refs.canvas; |
||||
show_beautpic(this, canvas, 200); |
||||
}, watch: { |
||||
'$store.state.userinfo': function () { |
||||
if (this.$store.state.userinfo.domain_name) { |
||||
this.$store.dispatch("dodomainshow", false); |
||||
} else { |
||||
this.$store.dispatch("dodomainshow", true); |
||||
} |
||||
}, |
||||
'$store.state.domain_action': function () { |
||||
if (this.$store.state.domain_action) { |
||||
this.$store.dispatch("dodomainaction", false); |
||||
this.bind_domain_sure = true; |
||||
} |
||||
}, |
||||
} |
||||
, methods: { |
||||
canvas_move(e) { |
||||
this.mousePosition.x = e.pageX; |
||||
this.mousePosition.y = e.pageY; |
||||
}, |
||||
// eslint-disable-next-line no-unused-vars |
||||
canvas_leave(e) { |
||||
let canvas = this.$refs.canvas; |
||||
this.mousePosition.x = canvas.width / 2; |
||||
this.mousePosition.y = canvas.height / 2; |
||||
}, |
||||
} |
||||
export default { |
||||
name: "FirBase", |
||||
components: {FirFooter, FirHeader, BackToTop, BindDomain}, |
||||
data() { |
||||
return { |
||||
mousePosition: {}, |
||||
bind_domain_sure: false, |
||||
bind_domain_title: '绑定下载页域名', |
||||
bind_domain_type: 1, |
||||
active: 1, |
||||
domain_name: '', |
||||
bind_status: false, |
||||
domain_tData: [{'type': 'CNAME', 'host': 'xxx', 'dns': 'demo.xxx.cn'}], |
||||
myBackToTopStyle: { |
||||
right: '80px', |
||||
bottom: '100px', |
||||
width: '40px', |
||||
height: '40px', |
||||
'border-radius': '4px', |
||||
'line-height': '45px', |
||||
background: '#e7eaf1' |
||||
} |
||||
} |
||||
}, |
||||
mounted() { |
||||
let canvas = this.$refs.canvas; |
||||
show_beautpic(this, canvas, 200); |
||||
}, watch: { |
||||
'$store.state.userinfo': function () { |
||||
if (this.$store.state.userinfo.domain_name) { |
||||
this.$store.dispatch("dodomainshow", false); |
||||
} else { |
||||
this.$store.dispatch("dodomainshow", true); |
||||
} |
||||
}, |
||||
'$store.state.domain_action': function () { |
||||
if (this.$store.state.domain_action) { |
||||
if (this.$store.state.domain_action === 2) { |
||||
this.bind_domain_title = '绑定下载码域名'; |
||||
this.bind_domain_type = 0 |
||||
} else { |
||||
this.bind_domain_title = '绑定下载页域名'; |
||||
this.bind_domain_type = 1 |
||||
} |
||||
this.$store.dispatch("dodomainaction", 0); |
||||
this.bind_domain_sure = true; |
||||
} |
||||
}, |
||||
} |
||||
, methods: { |
||||
canvas_move(e) { |
||||
this.mousePosition.x = e.pageX; |
||||
this.mousePosition.y = e.pageY; |
||||
}, |
||||
// eslint-disable-next-line no-unused-vars |
||||
canvas_leave(e) { |
||||
let canvas = this.$refs.canvas; |
||||
this.mousePosition.x = canvas.width / 2; |
||||
this.mousePosition.y = canvas.height / 2; |
||||
}, |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style scoped> |
||||
.pbody { |
||||
padding-top: 30px; |
||||
} |
||||
.pbody { |
||||
padding-top: 30px; |
||||
} |
||||
|
||||
.domian-tip-bar { |
||||
line-height: 43px; |
||||
color: #fff; |
||||
font-weight: 500; |
||||
font-size: medium; |
||||
margin-right: 20px; |
||||
} |
||||
.domain-tip-bar { |
||||
line-height: 43px; |
||||
color: #fff; |
||||
font-weight: 500; |
||||
font-size: medium; |
||||
margin-right: 20px; |
||||
} |
||||
|
||||
/deep/ .el-alert { |
||||
padding: 2px 16px; |
||||
} |
||||
</style> |
||||
|
@ -1,64 +1,51 @@ |
||||
<template> |
||||
<div class="ifooter"> |
||||
<div class="ifooter"> |
||||
|
||||
<div style="width: 300px; margin: 0 auto; padding: 5px 0;"> |
||||
<el-link :underline="false"> {{ footer.copyright }}</el-link> |
||||
</div> |
||||
<div style="width: 300px; margin: 0 auto; padding: 5px 0;"> |
||||
<a style="display: inline-block; text-decoration: none; height: 20px; line-height: 20px;" |
||||
:href="footer.gongAnBeiAn.url" |
||||
target="_blank" rel="noopener"> |
||||
<img style="float: left;" src="@/assets/beianlogo.png" alt=""/> |
||||
<el-link :underline="false" |
||||
style="float: left; height: 20px; line-height: 20px; margin: 0 0 0 5px; color: #939393;"> |
||||
{{ footer.gongAnBeiAn.text }} |
||||
</el-link> |
||||
</a> |
||||
<div style="width: 300px; margin: 0 auto; padding: 5px 0;"> |
||||
<el-link :underline="false"> {{ footer.copyright }}</el-link> |
||||
</div> |
||||
<div style="width: 300px; margin: 0 auto; padding: 5px 0;"> |
||||
<a :href="footer.gongAnBeiAn.url" |
||||
rel="noopener" |
||||
style="display: inline-block; text-decoration: none; height: 20px; line-height: 20px;" target="_blank"> |
||||
<img alt="" src="@/assets/beianlogo.png" style="float: left;"/> |
||||
<el-link :underline="false" |
||||
style="float: left; height: 20px; line-height: 20px; margin: 0 0 0 5px; color: #939393;"> |
||||
{{ footer.gongAnBeiAn.text }} |
||||
</el-link> |
||||
</a> |
||||
|
||||
</div> |
||||
</div> |
||||
|
||||
<div> |
||||
<div :underline="false" style="width: 200px; margin: 0 auto; padding: 5px 0;"> |
||||
<el-link :underline="false" :href="footer.ipcBeiAn.url" target="_blank" |
||||
rel="nofollow noopener">{{ footer.ipcBeiAn.text }} |
||||
</el-link> |
||||
</div> |
||||
</div> |
||||
<div> |
||||
<div style="width: 200px; margin: 0 auto; padding: 5px 0;"> |
||||
<el-link :href="footer.ipcBeiAn.url" :underline="false" rel="nofollow noopener" |
||||
target="_blank">{{ footer.ipcBeiAn.text }} |
||||
</el-link> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
|
||||
export default { |
||||
name: "FirFooter", |
||||
data() { |
||||
return { |
||||
footer: { |
||||
copyright: '', |
||||
ipcBeiAn: { |
||||
url: '', |
||||
text: '', |
||||
}, |
||||
gongAnBeiAn: { |
||||
url: '', |
||||
text: '', |
||||
}, |
||||
} |
||||
} |
||||
}, methods: {}, created() { |
||||
}, mounted() { |
||||
this.footer = window.g.footer; |
||||
} |
||||
const footer = process.env.base_env.footer |
||||
export default { |
||||
name: "FirFooter", |
||||
data() { |
||||
return { |
||||
footer |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style scoped> |
||||
.ifooter { |
||||
margin: 20px auto 100px; |
||||
width: 1166px; |
||||
text-align: center; |
||||
font-size: 0; |
||||
border-radius: 10px; |
||||
} |
||||
.ifooter { |
||||
margin: 20px auto 100px; |
||||
width: 1166px; |
||||
text-align: center; |
||||
font-size: 0; |
||||
border-radius: 10px; |
||||
} |
||||
|
||||
</style> |
||||
|
@ -1,187 +1,213 @@ |
||||
<template> |
||||
<div style="background-color: rgba(162,193,230,0.18);"> |
||||
<el-container class="navbar-wrapper"> |
||||
<el-dialog |
||||
title="API Token" |
||||
:visible.sync="dialogVisible" |
||||
width="30%" |
||||
center |
||||
> |
||||
<span>可用于调用公开 API,可用于登录 fly-cli,请勿泄露您的 token</span> |
||||
<el-main> |
||||
<el-tooltip content="点击复制到剪贴板"> |
||||
<el-link type="primary" v-if="token" :underline="false" v-clipboard:copy="token" |
||||
v-clipboard:success="copy_success">{{ token }} |
||||
</el-link> |
||||
</el-tooltip> |
||||
</el-main> |
||||
<span slot="footer" class="dialog-footer"> |
||||
<div style="background-color: rgba(162,193,230,0.18);"> |
||||
<el-container class="navbar-wrapper"> |
||||
<el-dialog |
||||
:visible.sync="dialogVisible" |
||||
center |
||||
title="API Token" |
||||
width="30%" |
||||
> |
||||
<span>可用于调用公开 API,可用于登录 fly-cli,请勿泄露您的 token</span> |
||||
<el-main> |
||||
<el-tooltip content="点击复制到剪贴板"> |
||||
<el-link v-if="token" v-clipboard:copy="token" v-clipboard:success="copy_success" :underline="false" |
||||
type="primary">{{ token }} |
||||
</el-link> |
||||
</el-tooltip> |
||||
</el-main> |
||||
<span slot="footer" class="dialog-footer"> |
||||
<el-button type="primary" @click="maketoken">重新生成</el-button> |
||||
</span> |
||||
</el-dialog> |
||||
<el-row :gutter="20"> |
||||
<el-col :span="14" style="padding-top: 36px;margin-left: 60px"> |
||||
<el-breadcrumb separator-class="el-icon-arrow-right" style="height: 60px;font-size: 20px"> |
||||
<el-breadcrumb-item :to="{ name:'FirIndex' }">首页</el-breadcrumb-item> |
||||
<el-breadcrumb-item :to="{ name:'FirApps'}">我的应用</el-breadcrumb-item> |
||||
|
||||
<el-breadcrumb-item v-if="this.route_info.label" :to="{ name:route_info.name}">{{ |
||||
this.route_info.label }} |
||||
</el-breadcrumb-item> |
||||
|
||||
<el-breadcrumb-item v-if="$store.state.currentapp.name" |
||||
:to="{name: 'FirAppInfostimeline', params: {id: $store.state.currentapp.app_id}}"> |
||||
{{ $store.state.currentapp.name}} |
||||
</el-breadcrumb-item> |
||||
|
||||
</el-breadcrumb> |
||||
</el-col> |
||||
<el-col :span="2" :push="2" style="padding-top: 16px;"> |
||||
<div class="block"> |
||||
<el-avatar :size="66" :src="$store.state.userinfo.head_img"></el-avatar> |
||||
</div> |
||||
</el-col> |
||||
<el-col :span="4" :push="2" style="padding-top: 16px"> |
||||
<el-dropdown style="padding-top: 12px;" @command="handleCommand"> |
||||
<el-button type="primary" plain round> |
||||
{{$store.state.userinfo.first_name }}<i class="el-icon-arrow-down el-icon--right"></i> |
||||
</el-button> |
||||
<el-dropdown-menu slot="dropdown"> |
||||
<el-dropdown-item command="userinfo">个人资料</el-dropdown-item> |
||||
<el-dropdown-item command="apitoken">API token</el-dropdown-item> |
||||
<el-dropdown-item command="setdomian">设置域名</el-dropdown-item> |
||||
<el-dropdown-item command="storage" v-if="$store.state.userinfo.storage_active">存储管理 |
||||
</el-dropdown-item> |
||||
<el-dropdown-item command="supersign" v-if="$store.state.userinfo.supersign_active">超级签名 |
||||
</el-dropdown-item> |
||||
<el-dropdown-item command="myorder">订单信息</el-dropdown-item> |
||||
<el-dropdown-item command="exit">退出</el-dropdown-item> |
||||
|
||||
</el-dropdown-menu> |
||||
</el-dropdown> |
||||
|
||||
</el-col> |
||||
|
||||
</el-row> |
||||
|
||||
|
||||
</el-container> |
||||
</div> |
||||
</el-dialog> |
||||
<el-row :gutter="20"> |
||||
<el-col :span="14" style="padding-top: 36px;margin-left: 60px"> |
||||
<el-breadcrumb separator-class="el-icon-arrow-right" style="height: 60px;font-size: 20px"> |
||||
<el-breadcrumb-item :to="{ name:'FirIndex' }">首页</el-breadcrumb-item> |
||||
<el-breadcrumb-item :to="{ name:'FirApps'}">我的应用</el-breadcrumb-item> |
||||
|
||||
<el-breadcrumb-item v-if="this.route_info.label" :to="{ name:route_info.name}">{{ |
||||
this.route_info.label |
||||
}} |
||||
</el-breadcrumb-item> |
||||
|
||||
<el-breadcrumb-item v-if="$store.state.currentapp.name" |
||||
:to="{name: 'FirAppInfostimeline', params: {id: $store.state.currentapp.app_id}}"> |
||||
{{ $store.state.currentapp.name }} |
||||
</el-breadcrumb-item> |
||||
|
||||
</el-breadcrumb> |
||||
</el-col> |
||||
<el-col :push="2" :span="2" style="padding-top: 16px;"> |
||||
<div class="block"> |
||||
<el-avatar :size="66" :src="$store.state.userinfo.head_img"></el-avatar> |
||||
</div> |
||||
</el-col> |
||||
<el-col :push="2" :span="4" style="padding-top: 16px"> |
||||
<el-dropdown style="padding-top: 12px;" @command="handleCommand"> |
||||
<el-button plain round type="primary"> |
||||
{{ $store.state.userinfo.first_name }}<i class="el-icon-arrow-down el-icon--right"></i> |
||||
</el-button> |
||||
<el-dropdown-menu slot="dropdown"> |
||||
<el-dropdown-item command="userinfo">个人资料</el-dropdown-item> |
||||
<el-dropdown-item command="apitoken">API token</el-dropdown-item> |
||||
<el-dropdown-item command="setdomian">设置域名</el-dropdown-item> |
||||
<el-dropdown-item command="download">下载配置</el-dropdown-item> |
||||
<el-dropdown-item command="setnotify">消息中心</el-dropdown-item> |
||||
<el-dropdown-item v-if="$store.state.userinfo.role>1" command="setadvert">宣传广告 |
||||
</el-dropdown-item> |
||||
<el-dropdown-item v-if="$store.state.userinfo.storage_active" command="storage">存储管理 |
||||
</el-dropdown-item> |
||||
<el-dropdown-item v-if="$store.state.userinfo.supersign_active" command="supersign">超级签名 |
||||
</el-dropdown-item> |
||||
<el-dropdown-item command="myorder">订单信息</el-dropdown-item> |
||||
<el-dropdown-item command="contact">联系我们</el-dropdown-item> |
||||
<el-dropdown-item command="qrcode">下载码</el-dropdown-item> |
||||
<el-dropdown-item command="exit">退出</el-dropdown-item> |
||||
|
||||
</el-dropdown-menu> |
||||
</el-dropdown> |
||||
|
||||
</el-col> |
||||
|
||||
</el-row> |
||||
|
||||
|
||||
</el-container> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import {apitoken, logout} from '@/restful' |
||||
|
||||
export default { |
||||
name: "FirHeader", |
||||
data() { |
||||
return { |
||||
current_user: {}, |
||||
appName: '', |
||||
token: '', |
||||
dialogVisible: false, |
||||
route_info: {'name': '', 'label': ''}, |
||||
} |
||||
}, methods: { |
||||
copy_success() { |
||||
this.$message.success('复制剪切板成功'); |
||||
}, |
||||
maketoken() { |
||||
apitoken(data => { |
||||
if (data.code === 1000) { |
||||
this.token = data.data.token; |
||||
this.$message({ |
||||
type: 'success', |
||||
message: '重新生成成功!' |
||||
}); |
||||
} else { |
||||
this.$message.error("失败了 " + data.msg) |
||||
} |
||||
}, {methods: 'PUT', token: this.token}); |
||||
}, |
||||
handleCommand(command) { |
||||
if (command === 'userinfo') { |
||||
this.$router.push({name: 'FirUserProfileInfo'}) |
||||
} else if (command === 'storage') { |
||||
this.$router.push({name: 'FirUserStorage', params: {act: "change"}}) |
||||
} else if (command === 'supersign') { |
||||
this.$store.dispatch('doucurrentapp', {}); |
||||
this.$router.push({"name": 'FirSuperSignBase', params: {act: "iosdeveloper"}}) |
||||
} else if (command === 'apitoken') { |
||||
apitoken(data => { |
||||
if (data.code === 1000) { |
||||
this.token = data.data.token; |
||||
this.dialogVisible = true; |
||||
} else { |
||||
this.dialogVisible = false; |
||||
this.$message.error("获取失败了 " + data.msg) |
||||
} |
||||
}, {methods: 'GET', token: this.token}); |
||||
|
||||
} else if (command === 'setdomian') { |
||||
this.$store.dispatch("dodomainaction", true); |
||||
} else if (command === 'myorder') { |
||||
this.$router.push({"name": 'FirUserOrders'}) |
||||
} else if (command === 'exit') { |
||||
logout(data => { |
||||
if (data.code === 1000) { |
||||
this.$message.success("退出成功"); |
||||
this.$cookies.remove("token"); |
||||
this.$cookies.remove("auth_token"); |
||||
this.$cookies.remove("username"); |
||||
this.$cookies.remove("first_name"); |
||||
this.$store.dispatch('doucurrentapp', {}); |
||||
this.$store.dispatch('doUserinfo', {}); |
||||
this.$router.push({name: 'FirLogin'}); |
||||
} else { |
||||
this.$message.error("退出失败") |
||||
} |
||||
}, {}) |
||||
} |
||||
}, |
||||
init_route_name() { |
||||
if (this.$route.meta) { |
||||
this.route_info.label = this.$route.meta.label; |
||||
this.route_info.name = this.$route.name; |
||||
} |
||||
}, |
||||
|
||||
}, created() { |
||||
this.appName = this.$route.params.id |
||||
}, watch: { |
||||
$route: function () { |
||||
this.appName = this.$route.params.id; |
||||
this.init_route_name(); |
||||
} |
||||
}, mounted() { |
||||
this.init_route_name(); |
||||
} |
||||
import {apitoken, logout} from '@/restful' |
||||
|
||||
export default { |
||||
name: "FirHeader", |
||||
data() { |
||||
return { |
||||
current_user: {}, |
||||
appName: '', |
||||
token: '', |
||||
dialogVisible: false, |
||||
route_info: {'name': '', 'label': ''}, |
||||
} |
||||
}, methods: { |
||||
copy_success() { |
||||
this.$message.success('复制剪切板成功'); |
||||
}, |
||||
maketoken() { |
||||
this.$confirm('该操作将导致老秘钥失效,确认重新生成新的密钥么?', '警告', { |
||||
type: 'warning' |
||||
}) |
||||
// eslint-disable-next-line no-unused-vars |
||||
.then(res => { |
||||
apitoken(data => { |
||||
if (data.code === 1000) { |
||||
this.token = data.data.token; |
||||
this.$message({ |
||||
type: 'success', |
||||
message: '重新生成成功!' |
||||
}); |
||||
} else { |
||||
this.$message.error("失败了 " + data.msg) |
||||
} |
||||
}, {methods: 'PUT', token: this.token}); |
||||
}) |
||||
.catch(err => { |
||||
this.$message.error(err) |
||||
}); |
||||
}, |
||||
handleCommand(command) { |
||||
if (command === 'userinfo') { |
||||
this.$router.push({name: 'FirUserProfileInfo'}) |
||||
} else if (command === 'storage') { |
||||
this.$router.push({name: 'FirUserStorage', params: {act: "change"}}) |
||||
} else if (command === 'supersign') { |
||||
this.$store.dispatch('doucurrentapp', {}); |
||||
this.$router.push({"name": 'FirSuperSignBase', params: {act: "iosdeveloper"}}) |
||||
} else if (command === 'apitoken') { |
||||
apitoken(data => { |
||||
if (data.code === 1000) { |
||||
this.token = data.data.token; |
||||
this.dialogVisible = true; |
||||
} else { |
||||
this.dialogVisible = false; |
||||
this.$message.error("获取失败了 " + data.msg) |
||||
} |
||||
}, {methods: 'GET', token: this.token}); |
||||
|
||||
} else if (command === 'setdomian') { |
||||
this.$router.push({"name": 'FirUserDomain'}) |
||||
} else if (command === 'download') { |
||||
this.$router.push({"name": 'FirUserDownload'}) |
||||
} else if (command === 'setadvert') { |
||||
this.$router.push({"name": 'FirUserAdvert'}) |
||||
} else if (command === 'myorder') { |
||||
this.$router.push({"name": 'FirUserOrders'}) |
||||
} else if (command === 'setnotify') { |
||||
this.$router.push({"name": 'FirUserNotify'}) |
||||
} else if (command === 'qrcode') { |
||||
this.$router.push({"name": 'FirUserQrcode'}) |
||||
} else if (command === 'contact') { |
||||
this.$router.push({"name": 'FirContact'}) |
||||
} else if (command === 'exit') { |
||||
logout(data => { |
||||
if (data.code === 1000) { |
||||
this.$message.success("退出成功"); |
||||
this.$cookies.remove("token"); |
||||
this.$cookies.remove("auth_token"); |
||||
this.$cookies.remove("username"); |
||||
this.$cookies.remove("first_name"); |
||||
this.$store.dispatch('doucurrentapp', {}); |
||||
this.$store.dispatch('doUserinfo', {}); |
||||
this.$router.push({name: 'FirLogin'}); |
||||
} else { |
||||
this.$message.error("退出失败") |
||||
} |
||||
}, {}) |
||||
} |
||||
}, |
||||
init_route_name() { |
||||
if (this.$route.meta) { |
||||
this.route_info.label = this.$route.meta.label; |
||||
this.route_info.name = this.$route.name; |
||||
} |
||||
}, |
||||
|
||||
}, created() { |
||||
this.appName = this.$route.params.id |
||||
}, watch: { |
||||
$route: function () { |
||||
this.appName = this.$route.params.id; |
||||
this.init_route_name(); |
||||
} |
||||
}, mounted() { |
||||
this.init_route_name(); |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style scoped> |
||||
|
||||
.el-container, .el-row { |
||||
margin: 10px auto; |
||||
width: 1166px; |
||||
} |
||||
.el-container, .el-row { |
||||
margin: 10px auto; |
||||
width: 1166px; |
||||
} |
||||
|
||||
.navbar-wrapper { |
||||
font-size: 0; |
||||
border-radius: 10px; |
||||
} |
||||
.navbar-wrapper { |
||||
font-size: 0; |
||||
border-radius: 10px; |
||||
} |
||||
|
||||
.el-dropdown { |
||||
vertical-align: top; |
||||
} |
||||
.el-dropdown { |
||||
vertical-align: top; |
||||
} |
||||
|
||||
.el-dropdown + .el-dropdown { |
||||
margin-left: 15px; |
||||
} |
||||
.el-dropdown + .el-dropdown { |
||||
margin-left: 15px; |
||||
} |
||||
|
||||
.el-icon-arrow-down { |
||||
font-size: 12px; |
||||
} |
||||
.el-icon-arrow-down { |
||||
font-size: 12px; |
||||
} |
||||
|
||||
|
||||
</style> |
||||
|
@ -1,317 +1,473 @@ |
||||
<template> |
||||
<el-container> |
||||
<div style="margin: 10px 0 10px 0 ;position:absolute;right:20px;top:auto;"> |
||||
<el-button round icon="el-icon-arrow-left" @click="$router.go(-1)"/> |
||||
<el-button round icon="el-icon-s-home" @click="$router.push({name:'FirIndex'})"/> |
||||
<el-container> |
||||
<div style="margin: 10px 0 10px 0 ;position:absolute;right:20px;top:auto;"> |
||||
<el-button icon="el-icon-arrow-left" round @click="$router.go(-1)"/> |
||||
<el-button icon="el-icon-s-home" round @click="$router.push({name:'FirIndex'})"/> |
||||
|
||||
</div> |
||||
<el-header> |
||||
|
||||
<div> |
||||
<span>登录</span> |
||||
</div> |
||||
|
||||
</el-header> |
||||
<el-main> |
||||
|
||||
<el-form ref="form" :model="form"> |
||||
|
||||
<el-tabs v-model="activeName"> |
||||
<el-tab-pane v-if="allow_ways.up" label="用户名登录" name="username"> |
||||
<el-form-item> |
||||
<el-input v-model="form.email" autofocus clearable placeholder="用户名" |
||||
prefix-icon="el-icon-user"/> |
||||
</el-form-item> |
||||
</el-tab-pane> |
||||
<el-tab-pane v-if="allow_ways.sms || allow_ways.email" :label="rutitle+'登录'" name="smsemail"> |
||||
<el-form-item> |
||||
<el-input v-model="form.email" :placeholder="rutitle" autofocus clearable |
||||
prefix-icon="el-icon-user"/> |
||||
</el-form-item> |
||||
</el-tab-pane> |
||||
|
||||
</el-tabs> |
||||
|
||||
<el-form-item v-if="is_captcha"> |
||||
<el-input v-model="form.password" clearable placeholder="密码" |
||||
prefix-icon="el-icon-lock" |
||||
show-password @keyup.enter.native="onSubmit"/> |
||||
</el-form-item> |
||||
<el-form-item v-else> |
||||
<el-input v-model="form.password" clearable placeholder="密码" |
||||
prefix-icon="el-icon-lock" show-password/> |
||||
</el-form-item> |
||||
<el-form-item v-if="captcha.captcha_image" style="height: 40px"> |
||||
<el-row style="height: 40px"> |
||||
<el-col :span="16"> |
||||
<el-input v-model="form.verify_code" clearable maxlength="6" |
||||
placeholder="请输入验证码" @keyup.enter.native="onSubmit"/> |
||||
</el-col> |
||||
<el-col :span="8"> |
||||
<el-image |
||||
:src="captcha.captcha_image" |
||||
fit="contain" |
||||
style="margin:0 4px;border-radius:4px;cursor:pointer;height: 40px" @click="get_auth_code"> |
||||
</el-image> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
|
||||
<el-form-item> |
||||
<div id="captcha" ref="captcha"></div> |
||||
</el-form-item> |
||||
|
||||
<el-form-item> |
||||
<el-button :disabled="login_disable" type="danger" @click="onSubmit">登录</el-button> |
||||
</el-form-item> |
||||
|
||||
<el-form-item v-if="register_enable"> |
||||
<el-button plain type="primary" @click="onRegister">注册</el-button> |
||||
</el-form-item> |
||||
<el-form-item> |
||||
<el-link :underline="false" plain @click="$router.push({name: 'FirResetPwd'})">忘记密码</el-link> |
||||
</el-form-item> |
||||
|
||||
<div v-if="allow_ways.third && JSON.stringify(allow_ways.third).indexOf('true')!==-1" class="other-way"> |
||||
<hr> |
||||
<el-popover |
||||
v-model="showuserlist" |
||||
placement="top" |
||||
title="该微信绑定了多个用户,请选择账户,并点击登录" |
||||
trigger="manual" |
||||
width="400"> |
||||
|
||||
<el-row style="margin-top: 20px"> |
||||
<el-col v-for="userinfo in userinfo_list" :key="userinfo.uid" :span="8" style="margin-left: 40px"> |
||||
<div @click="weixinlogin(userinfo)"> |
||||
<el-card :body-style="{textAlign:'center',padding:'8px',width:'120px'}" shadow="hover"> |
||||
<!-- <el-image :src="userinfo.head_img"></el-image>--> |
||||
<el-avatar :size="100" :src="userinfo.head_img"></el-avatar> |
||||
<div style="margin: 5px 0 5px"> |
||||
<span>{{ userinfo.first_name }}</span> |
||||
</div> |
||||
</el-card> |
||||
</div> |
||||
</el-col> |
||||
</el-row> |
||||
|
||||
<span slot="reference" class="info">或使用以下账户登录</span> |
||||
</el-popover> |
||||
|
||||
<el-popover |
||||
v-if="allow_ways.third && allow_ways.third.wxp" |
||||
v-model="wx_visible" |
||||
placement="top" |
||||
title="微信扫码关注公众号登录" |
||||
trigger="manual"> |
||||
<div> |
||||
<el-image :src="wx_login_qr_url" style="width: 176px;height: 166px"/> |
||||
</div> |
||||
<el-button slot="reference" |
||||
size="small" style="color: #1fc939;border: 1px solid rgba(31,201,57,.5); width: 110px" |
||||
@click="wxLogin">微信 |
||||
</el-button> |
||||
</el-popover> |
||||
|
||||
</div> |
||||
<el-header> |
||||
</el-form> |
||||
|
||||
<div> |
||||
<span>登录</span> |
||||
</div> |
||||
|
||||
</el-header> |
||||
<el-main> |
||||
|
||||
<el-form ref="form" :model="form"> |
||||
|
||||
<el-tabs v-model="activeName"> |
||||
<el-tab-pane label="用户名登录" name="username" v-if="allow_ways.up"> |
||||
<el-form-item> |
||||
<el-input v-model="form.email" prefix-icon="el-icon-user" placeholder="用户名" autofocus |
||||
clearable/> |
||||
</el-form-item> |
||||
</el-tab-pane> |
||||
<el-tab-pane :label="rutitle+'登录'" name="smsemail" v-if="allow_ways.sms || allow_ways.email"> |
||||
<el-form-item> |
||||
<el-input v-model="form.email" prefix-icon="el-icon-user" :placeholder="rutitle" autofocus |
||||
clearable/> |
||||
</el-form-item> |
||||
</el-tab-pane> |
||||
|
||||
</el-tabs> |
||||
|
||||
<el-form-item v-if="is_cptch"> |
||||
<el-input v-model="form.password" prefix-icon="el-icon-lock" placeholder="密码" |
||||
@keyup.enter.native="onSubmit" |
||||
show-password clearable/> |
||||
</el-form-item> |
||||
<el-form-item v-else> |
||||
<el-input v-model="form.password" prefix-icon="el-icon-lock" placeholder="密码" |
||||
show-password clearable/> |
||||
</el-form-item> |
||||
<el-form-item style="height: 40px" v-if="cptch.cptch_image"> |
||||
<el-row style="height: 40px"> |
||||
<el-col :span="16"> |
||||
<el-input placeholder="请输入验证码" v-model="form.authcode" maxlength="6" |
||||
@keyup.enter.native="onSubmit" clearable/> |
||||
</el-col> |
||||
<el-col :span="8"> |
||||
<el-image |
||||
style="margin:0 4px;border-radius:4px;cursor:pointer;height: 40px" |
||||
:src="cptch.cptch_image" |
||||
fit="contain" @click="get_auth_code"> |
||||
</el-image> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
|
||||
<el-form-item> |
||||
<div id="captcha" ref="captcha"></div> |
||||
</el-form-item> |
||||
|
||||
<el-form-item> |
||||
<el-button type="danger" :disabled="login_disable" @click="onSubmit">登录</el-button> |
||||
</el-form-item> |
||||
|
||||
<el-form-item v-if="register_enable"> |
||||
<el-button type="primary" @click="onRegister" plain>注册</el-button> |
||||
</el-form-item> |
||||
<el-form-item> |
||||
<el-link :underline="false" @click="$router.push({name: 'FirResetPwd'})" plain>忘记密码</el-link> |
||||
</el-form-item> |
||||
</el-form> |
||||
|
||||
|
||||
</el-main> |
||||
|
||||
|
||||
</el-container> |
||||
</el-main> |
||||
|
||||
|
||||
</el-container> |
||||
|
||||
</template> |
||||
|
||||
<script> |
||||
import {loginFun, set_auth_token} from "@/restful"; |
||||
import {checkEmail, checkphone, geetest} from "@/utils"; |
||||
|
||||
export default { |
||||
name: "FirLogin", |
||||
data() { |
||||
return { |
||||
form: { |
||||
email: '', |
||||
password: '', |
||||
authcode: '' |
||||
}, |
||||
cptch: {"cptch_image": '', "cptch_key": '', "length": 8}, |
||||
activeName: 'username', |
||||
allow_ways: {}, |
||||
rutitle: '', |
||||
rctitle: '', |
||||
register_enable: false, |
||||
login_disable: false, |
||||
} |
||||
}, |
||||
methods: { |
||||
is_cptch() { |
||||
let cptch_flag = this.form.authcode.length === this.cptch.length; |
||||
if (this.cptch.cptch_key === '' || !this.cptch.cptch_key) { |
||||
cptch_flag = true |
||||
} |
||||
return cptch_flag |
||||
}, |
||||
onSubmit() { |
||||
let email = this.form.email; |
||||
let password = this.form.password; |
||||
let authcode = this.form.authcode; |
||||
let login_type = 'up'; |
||||
let cptch_flag = this.form.authcode.length === this.cptch.length; |
||||
if (this.cptch.cptch_key === '' || !this.cptch.cptch_key) { |
||||
cptch_flag = true |
||||
} |
||||
if (cptch_flag) { |
||||
|
||||
if (this.activeName === "username") { |
||||
if (email.length < 6) { |
||||
this.$message({ |
||||
message: '用户名至少6位', |
||||
type: 'error' |
||||
}); |
||||
return |
||||
} |
||||
|
||||
} else if (this.activeName === "smsemail") { |
||||
let checkp = checkphone(this.form.email); |
||||
let checke = checkEmail(this.form.email); |
||||
if (!checkp && !checke) { |
||||
this.$message({ |
||||
message: '邮箱或者手机号输入有误', |
||||
type: 'error' |
||||
}); |
||||
return |
||||
} |
||||
if (checkp) { |
||||
login_type = 'sms'; |
||||
} else if (checke) { |
||||
login_type = 'email'; |
||||
} |
||||
} else { |
||||
this.$message({ |
||||
message: '未知登录方式', |
||||
type: 'error' |
||||
}); |
||||
return |
||||
} |
||||
if (password.length > 6) { |
||||
let params = { |
||||
"username": email, |
||||
"password": password, |
||||
"authcode": authcode, |
||||
"cptch_key": this.cptch.cptch_key, |
||||
"login_type": login_type, |
||||
}; |
||||
this.login_disable = true; |
||||
if (this.cptch.geetest) { |
||||
geetest(this, params, (n_params) => { |
||||
this.do_login(n_params); |
||||
}) |
||||
} else { |
||||
this.do_login(params) |
||||
} |
||||
} else { |
||||
this.$message({ |
||||
message: '密码长度过短', |
||||
type: 'warning' |
||||
}); |
||||
} |
||||
} else { |
||||
this.$message({ |
||||
message: '验证码有误', |
||||
type: 'warning' |
||||
}); |
||||
} |
||||
}, |
||||
do_login(params) { |
||||
loginFun(data => { |
||||
if (data.code === 1000) { |
||||
this.$message({ |
||||
message: '登录成功', |
||||
type: 'success' |
||||
}); |
||||
this.$cookies.remove("auth_token"); |
||||
this.$cookies.set("token", data['token'], 3600 * 24 * 30); |
||||
this.$cookies.set("username", data.userinfo.username, 3600 * 24 * 30); |
||||
this.$cookies.set("first_name", data.userinfo.first_name, 3600 * 24 * 30); |
||||
this.$store.dispatch("doUserinfo", data.userinfo); |
||||
set_auth_token(); |
||||
this.$router.push({name: 'FirApps'}) |
||||
} else { |
||||
this.$message({ |
||||
message: data.msg, |
||||
type: 'error' |
||||
}); |
||||
this.get_auth_code(); |
||||
} |
||||
this.login_disable = false; |
||||
}, { |
||||
"methods": "POST", |
||||
"data": params |
||||
}); |
||||
}, |
||||
onRegister() { |
||||
this.$router.push({name: 'FirRegist'}) |
||||
}, |
||||
set_activename() { |
||||
if (this.allow_ways.up) { |
||||
this.activeName = 'username'; |
||||
} else { |
||||
this.activeName = 'smsemail'; |
||||
} |
||||
}, |
||||
set_rtitle() { |
||||
this.rutitle = ''; |
||||
if (this.allow_ways.sms) { |
||||
this.rutitle = this.rutitle + '手机号 '; |
||||
} |
||||
if (this.allow_ways.email) { |
||||
this.rutitle = this.rutitle + '邮箱 '; |
||||
} |
||||
|
||||
this.rutitle = this.rutitle.trim().replace(' ', '或'); |
||||
}, |
||||
get_auth_code() { |
||||
loginFun(data => { |
||||
if (data.code === 1000) { |
||||
this.cptch = data.data; |
||||
this.allow_ways = data.data.login_type; |
||||
this.register_enable = data.data.register_enable; |
||||
this.form.authcode = ''; |
||||
this.set_rtitle(); |
||||
this.set_activename(); |
||||
} else { |
||||
this.$message({ |
||||
message: data.msg, |
||||
type: 'error' |
||||
}); |
||||
} |
||||
}, { |
||||
"methods": "GET", |
||||
"data": {} |
||||
}); |
||||
}, |
||||
}, |
||||
mounted() { |
||||
this.get_auth_code(); |
||||
}, created() { |
||||
} |
||||
import {loginFun, wxLoginFun} from "@/restful"; |
||||
import {geetest} from "@/utils"; |
||||
import {checkEmail, checkphone, getRandomStr} from "@/utils/base/utils"; |
||||
|
||||
export default { |
||||
name: "FirLogin", |
||||
data() { |
||||
return { |
||||
form: { |
||||
email: '', |
||||
password: '', |
||||
verify_code: '' |
||||
}, |
||||
captcha: {"captcha_image": '', "captcha_key": '', "length": 8}, |
||||
auth_rules: {}, |
||||
activeName: 'username', |
||||
allow_ways: {'third': {}}, |
||||
rutitle: '', |
||||
rctitle: '', |
||||
register_enable: false, |
||||
login_disable: false, |
||||
wx_login_qr_url: '', |
||||
wx_visible: false, |
||||
loop_flag: false, |
||||
unique_key: '', |
||||
userinfo_list: [], |
||||
unique_wid: '', |
||||
showuserlist: false |
||||
} |
||||
}, |
||||
methods: { |
||||
weixinlogin(userinfo) { |
||||
wxLoginFun(data => { |
||||
if (data.code === 1000) { |
||||
this.set_cookie_and_token(data); |
||||
} else if (data.code === 1005) { |
||||
this.$message.error(data.msg) |
||||
} else { |
||||
this.showuserlist = false |
||||
this.$message.error(data.msg) |
||||
} |
||||
}, { |
||||
'methods': 'PUT', |
||||
'data': {uid: userinfo.uid, token: userinfo.token, 'wid': this.unique_wid} |
||||
}) |
||||
}, |
||||
set_cookie_and_token(data) { |
||||
this.$cookies.remove("auth_token"); |
||||
this.$cookies.set("token", data['token'], 3600 * 24 * 30); |
||||
this.$cookies.set("username", data.userinfo.username, 3600 * 24 * 30); |
||||
this.$cookies.set("first_name", data.userinfo.first_name, 3600 * 24 * 30); |
||||
this.$store.dispatch("doUserinfo", data.userinfo); |
||||
this.$router.push({name: 'FirApps'}) |
||||
}, |
||||
loop_get_wx_info(wx_login_ticket, c_count = 1, unique_key = getRandomStr()) { |
||||
if (wx_login_ticket && wx_login_ticket.length < 3) { |
||||
this.$message.error("获取登陆码失败,请稍后再试"); |
||||
return |
||||
} |
||||
if (!this.wx_visible) { |
||||
return; |
||||
} |
||||
wxLoginFun(data => { |
||||
c_count += 1; |
||||
if (c_count > 30) { |
||||
return; |
||||
} |
||||
if (data.code === 1000) { |
||||
this.set_cookie_and_token(data); |
||||
} else if (data.code === 1005) { |
||||
this.wx_visible = false; |
||||
this.loop_flag = false; |
||||
this.$message({ |
||||
message: data.msg, |
||||
type: 'error', |
||||
duration: 30000 |
||||
}); |
||||
} else if (data.code === 1004) { |
||||
this.loop_flag = false; |
||||
} else if (data.code === 1006) { |
||||
return this.loop_get_wx_info(wx_login_ticket, c_count, unique_key) |
||||
} else if (data.code === 2000) { |
||||
this.wx_visible = false; |
||||
this.loop_flag = false; |
||||
this.userinfo_list = data.data; |
||||
this.unique_wid = data.wid; |
||||
this.showuserlist = true |
||||
} |
||||
}, { |
||||
"methods": "POST", |
||||
data: {"ticket": wx_login_ticket, "unique_key": unique_key} |
||||
}) |
||||
// }, 3000) |
||||
|
||||
}, |
||||
wxLogin() { |
||||
this.wx_visible = !this.wx_visible; |
||||
this.wx_login_qr_url = ''; |
||||
if (this.wx_visible) { |
||||
wxLoginFun(data => { |
||||
if (data.code === 1000) { |
||||
this.wx_login_qr_url = data.data.qr; |
||||
this.loop_flag = true; |
||||
this.loop_get_wx_info(data.data.ticket); |
||||
} else { |
||||
this.$message.error(data.msg); |
||||
this.wx_visible = false; |
||||
this.loop_flag = false; |
||||
} |
||||
}, { |
||||
"methods": "GET", "data": {"unique_key": this.unique_key} |
||||
}) |
||||
} else { |
||||
this.loop_flag = false; |
||||
} |
||||
}, |
||||
is_captcha() { |
||||
let captcha_flag = this.form.verify_code.length === this.captcha.length; |
||||
if (this.captcha.captcha_key === '' || !this.captcha.captcha_key) { |
||||
captcha_flag = true |
||||
} |
||||
return captcha_flag |
||||
}, |
||||
onSubmit() { |
||||
let email = this.form.email; |
||||
let password = this.form.password; |
||||
let verify_code = this.form.verify_code; |
||||
let login_type = 'up'; |
||||
let captcha_flag = this.form.verify_code.length === this.captcha.length; |
||||
if (this.captcha.captcha_key === '' || !this.captcha.captcha_key) { |
||||
captcha_flag = true |
||||
} |
||||
if (captcha_flag) { |
||||
|
||||
if (this.activeName === "username") { |
||||
if (email.length < 6) { |
||||
this.$message({ |
||||
message: '用户名至少6位', |
||||
type: 'error' |
||||
}); |
||||
return |
||||
} |
||||
|
||||
} else if (this.activeName === "smsemail") { |
||||
let checkp = checkphone(this.form.email); |
||||
let checke = checkEmail(this.form.email); |
||||
if (!checkp && !checke) { |
||||
this.$message({ |
||||
message: '邮箱或者手机号输入有误', |
||||
type: 'error' |
||||
}); |
||||
return |
||||
} |
||||
if (checkp) { |
||||
login_type = 'sms'; |
||||
} else if (checke) { |
||||
login_type = 'email'; |
||||
} |
||||
} else { |
||||
this.$message({ |
||||
message: '未知登录方式', |
||||
type: 'error' |
||||
}); |
||||
return |
||||
} |
||||
if (password.length >= 6) { |
||||
let params = { |
||||
"username": email, |
||||
"password": password, |
||||
"verify_code": verify_code, |
||||
"captcha_key": this.captcha.captcha_key, |
||||
"login_type": login_type, |
||||
}; |
||||
this.login_disable = true; |
||||
if (this.auth_rules.geetest) { |
||||
geetest(this, this.form.email, params, (n_params) => { |
||||
this.do_login(n_params); |
||||
}) |
||||
} else { |
||||
this.do_login(params) |
||||
} |
||||
} else { |
||||
this.$message({ |
||||
message: '密码长度过短', |
||||
type: 'warning' |
||||
}); |
||||
} |
||||
} else { |
||||
this.$message({ |
||||
message: '验证码有误', |
||||
type: 'warning' |
||||
}); |
||||
} |
||||
}, |
||||
do_login(params) { |
||||
loginFun(data => { |
||||
if (data.code === 1000) { |
||||
this.$message({ |
||||
message: '登录成功', |
||||
type: 'success' |
||||
}); |
||||
this.set_cookie_and_token(data); |
||||
} else { |
||||
this.$message({ |
||||
message: data.msg, |
||||
type: 'error' |
||||
}); |
||||
this.get_auth_code(); |
||||
} |
||||
this.login_disable = false; |
||||
}, { |
||||
"methods": "POST", |
||||
"data": params |
||||
}); |
||||
}, |
||||
onRegister() { |
||||
this.$router.push({name: 'FirRegist'}) |
||||
}, |
||||
set_activename() { |
||||
if (this.allow_ways.up) { |
||||
this.activeName = 'username'; |
||||
} else { |
||||
this.activeName = 'smsemail'; |
||||
} |
||||
}, |
||||
set_rtitle() { |
||||
this.rutitle = ''; |
||||
if (this.allow_ways.sms) { |
||||
this.rutitle = this.rutitle + '手机号 '; |
||||
} |
||||
if (this.allow_ways.email) { |
||||
this.rutitle = this.rutitle + '邮箱 '; |
||||
} |
||||
|
||||
this.rutitle = this.rutitle.trim().replace(' ', '或'); |
||||
}, |
||||
get_auth_code() { |
||||
loginFun(data => { |
||||
if (data.code === 1000) { |
||||
this.auth_rules = data.data.auth_rules |
||||
this.captcha = this.auth_rules.captcha; |
||||
this.allow_ways = data.data.login_type; |
||||
this.register_enable = data.data.register_enable; |
||||
this.form.verify_code = ''; |
||||
this.set_rtitle(); |
||||
this.set_activename(); |
||||
} else { |
||||
this.$message({ |
||||
message: data.msg, |
||||
type: 'error' |
||||
}); |
||||
} |
||||
}, { |
||||
"methods": "GET", |
||||
"data": {} |
||||
}); |
||||
}, |
||||
}, |
||||
mounted() { |
||||
this.get_auth_code(); |
||||
this.unique_key = getRandomStr(); |
||||
}, created() { |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style scoped> |
||||
|
||||
.el-container { |
||||
margin: 10px auto; |
||||
width: 1266px; |
||||
} |
||||
|
||||
.el-header { |
||||
margin-top: 13%; |
||||
} |
||||
|
||||
.el-form { |
||||
max-width: 360px; |
||||
margin: 0 auto; |
||||
} |
||||
|
||||
.el-form-item .el-button { |
||||
max-width: 360px; |
||||
/*padding: 16px 20px;*/ |
||||
width: 100%; |
||||
position: relative; |
||||
height: 50px; |
||||
|
||||
} |
||||
|
||||
.el-header { |
||||
text-align: center; |
||||
overflow: hidden; |
||||
margin-bottom: 50px |
||||
} |
||||
|
||||
|
||||
.el-header div span { |
||||
font-size: 24px; |
||||
display: inline-block; |
||||
vertical-align: middle; |
||||
padding: 8px 40px |
||||
} |
||||
|
||||
.el-header div:before, .el-header div:after { |
||||
content: ' '; |
||||
display: inline-block; |
||||
vertical-align: middle; |
||||
width: 50%; |
||||
height: 1px; |
||||
background-color: #babfc3; |
||||
margin: 0 0 0 -50% |
||||
} |
||||
|
||||
.el-header div { |
||||
text-align: center |
||||
} |
||||
|
||||
.el-header div:after { |
||||
margin: 0 -50% 0 0 |
||||
} |
||||
.other-way { |
||||
position: relative; |
||||
text-align: center; |
||||
} |
||||
|
||||
.other-way hr { |
||||
height: 1px; |
||||
margin: 30px 0; |
||||
border: 0; |
||||
background-color: #e4e7ed; |
||||
} |
||||
|
||||
.other-way span.info { |
||||
font-size: 12px; |
||||
line-height: 1; |
||||
position: absolute; |
||||
top: -6px; |
||||
left: 50%; |
||||
padding: 0 10px; |
||||
transform: translate(-50%, 0); |
||||
color: #9ba3af; |
||||
} |
||||
|
||||
.el-container { |
||||
margin: 10px auto; |
||||
width: 1266px; |
||||
} |
||||
|
||||
.el-header { |
||||
margin-top: 13%; |
||||
} |
||||
|
||||
.el-form { |
||||
max-width: 360px; |
||||
margin: 0 auto; |
||||
} |
||||
|
||||
.el-form-item .el-button { |
||||
max-width: 360px; |
||||
/*padding: 16px 20px;*/ |
||||
width: 100%; |
||||
position: relative; |
||||
height: 50px; |
||||
|
||||
} |
||||
|
||||
.el-header { |
||||
text-align: center; |
||||
overflow: hidden; |
||||
margin-bottom: 50px |
||||
} |
||||
|
||||
|
||||
.el-header div span { |
||||
font-size: 24px; |
||||
display: inline-block; |
||||
vertical-align: middle; |
||||
padding: 8px 40px |
||||
} |
||||
|
||||
.el-header div:before, .el-header div:after { |
||||
content: ' '; |
||||
display: inline-block; |
||||
vertical-align: middle; |
||||
width: 50%; |
||||
height: 1px; |
||||
background-color: #babfc3; |
||||
margin: 0 0 0 -50% |
||||
} |
||||
|
||||
.el-header div { |
||||
text-align: center |
||||
} |
||||
|
||||
.el-header div:after { |
||||
margin: 0 -50% 0 0 |
||||
} |
||||
</style> |
||||
|
@ -1,389 +1,392 @@ |
||||
<template> |
||||
<el-container> |
||||
<div style="margin: 10px 0 10px 0 ;position:absolute;right:20px;top:auto;"> |
||||
<el-button round icon="el-icon-arrow-left" @click="$router.go(-1)"/> |
||||
<el-button round icon="el-icon-s-home" @click="$router.push({name:'FirIndex'})"/> |
||||
|
||||
</div> |
||||
<el-header> |
||||
|
||||
<div> |
||||
<span>注册</span> |
||||
</div> |
||||
|
||||
</el-header> |
||||
<el-main v-if="allow_r"> |
||||
|
||||
<el-form ref="form" :model="form"> |
||||
|
||||
<el-form-item v-if="allow_ways.code"> |
||||
<el-input v-model="form.icode" prefix-icon="el-icon-postcard" placeholder="邀请码必填" clearable |
||||
/> |
||||
</el-form-item> |
||||
|
||||
<el-form-item> |
||||
<el-input v-model="form.email" prefix-icon="el-icon-user" :placeholder="rutitle" autofocus |
||||
clearable/> |
||||
</el-form-item> |
||||
|
||||
<el-form-item style="height: 40px" v-if="cptch.cptch_image"> |
||||
<el-row style="height: 40px"> |
||||
<el-col :span="16"> |
||||
<el-input placeholder="请输入图片验证码" v-model="form.authcode" maxlength="6" clearable/> |
||||
</el-col> |
||||
<el-col :span="8"> |
||||
<el-image |
||||
style="margin:0 4px;border-radius:4px;cursor:pointer;height: 40px" |
||||
:src="cptch.cptch_image" |
||||
fit="contain" @click="get_auth_code"> |
||||
</el-image> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
|
||||
|
||||
<el-form-item> |
||||
<el-row> |
||||
<el-col :span="16"> |
||||
<el-input v-model="form.seicode" prefix-icon="el-icon-mobile" |
||||
placeholder="验证码" clearable/> |
||||
</el-col> |
||||
<el-col :span="8"> |
||||
<el-button type="info" @click="getphonecode" plain |
||||
style="margin:0 4px;border-radius:4px;cursor:pointer;height: 40px">获取验证码 |
||||
</el-button> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
|
||||
|
||||
<el-form-item> |
||||
<el-input v-model="form.password" prefix-icon="el-icon-lock" placeholder="密码" |
||||
show-password clearable/> |
||||
</el-form-item> |
||||
<el-form-item> |
||||
<el-input v-model="form.password2" prefix-icon="el-icon-lock" placeholder="确认密码" |
||||
show-password @keyup.enter.native="onRegist" clearable/> |
||||
</el-form-item> |
||||
|
||||
<el-form-item> |
||||
<div id="captcha" ref="captcha"></div> |
||||
</el-form-item> |
||||
|
||||
<el-form-item> |
||||
<el-button type="danger" @click="onRegist" :disabled="register_disable">注册</el-button> |
||||
</el-form-item> |
||||
|
||||
<el-form-item> |
||||
<el-button type="primary" @click="onLogin" plain>我是老用户,要登录</el-button> |
||||
</el-form-item> |
||||
</el-form> |
||||
|
||||
|
||||
</el-main> |
||||
|
||||
|
||||
</el-container> |
||||
<el-container> |
||||
<div style="margin: 10px 0 10px 0 ;position:absolute;right:20px;top:auto;"> |
||||
<el-button icon="el-icon-arrow-left" round @click="$router.go(-1)"/> |
||||
<el-button icon="el-icon-s-home" round @click="$router.push({name:'FirIndex'})"/> |
||||
|
||||
</div> |
||||
<el-header> |
||||
|
||||
<div> |
||||
<span>注册</span> |
||||
</div> |
||||
|
||||
</el-header> |
||||
<el-main v-if="allow_r"> |
||||
|
||||
<el-form ref="form" :model="form"> |
||||
|
||||
<el-form-item v-if="allow_ways.code"> |
||||
<el-input v-model="form.icode" clearable placeholder="邀请码必填" prefix-icon="el-icon-postcard" |
||||
/> |
||||
</el-form-item> |
||||
|
||||
<el-form-item> |
||||
<el-input v-model="form.email" :placeholder="rutitle" autofocus clearable |
||||
prefix-icon="el-icon-user"/> |
||||
</el-form-item> |
||||
|
||||
<el-form-item v-if="captcha.captcha_image" style="height: 40px"> |
||||
<el-row style="height: 40px"> |
||||
<el-col :span="16"> |
||||
<el-input v-model="form.verify_code" clearable maxlength="6" placeholder="请输入图片验证码"/> |
||||
</el-col> |
||||
<el-col :span="8"> |
||||
<el-image |
||||
:src="captcha.captcha_image" |
||||
fit="contain" |
||||
style="margin:0 4px;border-radius:4px;cursor:pointer;height: 40px" @click="get_auth_code"> |
||||
</el-image> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
|
||||
|
||||
<el-form-item> |
||||
<el-row> |
||||
<el-col :span="16"> |
||||
<el-input v-model="form.seicode" clearable |
||||
placeholder="验证码" prefix-icon="el-icon-mobile"/> |
||||
</el-col> |
||||
<el-col :span="8"> |
||||
<el-button plain style="margin:0 4px;border-radius:4px;cursor:pointer;height: 40px" type="info" |
||||
@click="getphonecode">获取验证码 |
||||
</el-button> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
|
||||
|
||||
<el-form-item> |
||||
<el-input v-model="form.password" clearable placeholder="密码" |
||||
prefix-icon="el-icon-lock" show-password/> |
||||
</el-form-item> |
||||
<el-form-item> |
||||
<el-input v-model="form.password2" clearable placeholder="确认密码" |
||||
prefix-icon="el-icon-lock" show-password @keyup.enter.native="onRegist"/> |
||||
</el-form-item> |
||||
|
||||
<el-form-item> |
||||
<div id="captcha" ref="captcha"></div> |
||||
</el-form-item> |
||||
|
||||
<el-form-item> |
||||
<el-button :disabled="register_disable" type="danger" @click="onRegist">注册</el-button> |
||||
</el-form-item> |
||||
|
||||
<el-form-item> |
||||
<el-button plain type="primary" @click="onLogin">我是老用户,要登录</el-button> |
||||
</el-form-item> |
||||
</el-form> |
||||
|
||||
|
||||
</el-main> |
||||
|
||||
|
||||
</el-container> |
||||
</template> |
||||
|
||||
<script> |
||||
import {getAuthTokenFun, registerFun} from "@/restful"; |
||||
import {checkEmail, checkphone, geetest} from "@/utils"; |
||||
|
||||
export default { |
||||
name: "FirRegist", |
||||
data() { |
||||
return { |
||||
form: { |
||||
email: '', |
||||
password: '', |
||||
password2: '', |
||||
authcode: '', |
||||
srccode: '', |
||||
seicode: '', |
||||
authtoken: '', |
||||
icode: '', |
||||
auth_token: '', |
||||
|
||||
}, |
||||
cptch: {"cptch_image": '', "cptch_key": '', "length": 8}, |
||||
allow_r: false, |
||||
allow_ways: {}, |
||||
rutitle: '', |
||||
register_disable: false, |
||||
} |
||||
}, |
||||
methods: { |
||||
set_rtitle() { |
||||
this.rutitle = ''; |
||||
if (this.allow_ways.sms) { |
||||
this.rutitle = this.rutitle + '手机号 '; |
||||
} |
||||
if (this.allow_ways.email) { |
||||
this.rutitle = this.rutitle + '邮箱 '; |
||||
} |
||||
|
||||
this.rutitle = this.rutitle.trim().replace(' ', '或'); |
||||
}, |
||||
get_auth_code() { |
||||
registerFun(data => { |
||||
if (data.code === 1000) { |
||||
let jdata = data.data; |
||||
if (jdata.enable) { |
||||
this.allow_r = true; |
||||
this.allow_ways = jdata.register_type; |
||||
this.form.authcode = ''; |
||||
this.set_rtitle(); |
||||
this.cptch = data.data; |
||||
} else { |
||||
this.allow_r = false; |
||||
this.$message({ |
||||
message: "该服务器不允许注册", |
||||
type: 'error' |
||||
}); |
||||
} |
||||
} else { |
||||
this.$message({ |
||||
message: data.msg, |
||||
type: 'error' |
||||
}); |
||||
} |
||||
}, { |
||||
"methods": "GET", |
||||
"data": {} |
||||
}); |
||||
}, |
||||
do_get_auth_token(params) { |
||||
getAuthTokenFun(data => { |
||||
if (data.code === 1000) { |
||||
this.$notify({ |
||||
title: '验证码', |
||||
message: '您正在进行注册,验证码已经发送您', |
||||
type: 'success' |
||||
}); |
||||
this.form.auth_token = data.data.auth_token; |
||||
} else { |
||||
this.$message({ |
||||
message: data.msg, |
||||
type: 'error' |
||||
}); |
||||
} |
||||
}, {"methods": 'POST', 'data': params}) |
||||
}, |
||||
getphonecode() { |
||||
let act = 'up'; |
||||
if (!this.docheck()) { |
||||
return |
||||
} |
||||
if (checkphone(this.form.email)) { |
||||
act = 'sms' |
||||
} |
||||
if (checkEmail(this.form.email)) { |
||||
act = 'email' |
||||
} |
||||
let authcode = this.form.authcode; |
||||
let cptch_flag = authcode.length === this.cptch.length; |
||||
if (this.cptch.cptch_key === '' || !this.cptch.cptch_key) { |
||||
cptch_flag = true |
||||
} |
||||
if (cptch_flag) { |
||||
let picode = { |
||||
"authcode": authcode, |
||||
"cptch_key": this.cptch.cptch_key, |
||||
"icode": this.form.icode, |
||||
}; |
||||
let params = {'act': act, 'target': this.form.email, 'ext': picode}; |
||||
if (this.cptch.geetest) { |
||||
geetest(this, params, (n_params) => { |
||||
this.do_get_auth_token(n_params); |
||||
}) |
||||
} else { |
||||
this.do_get_auth_token(params); |
||||
} |
||||
} else { |
||||
this.$message({ |
||||
message: '图片验证码有误', |
||||
type: 'warning' |
||||
}); |
||||
} |
||||
|
||||
}, |
||||
docheck() { |
||||
let checkp = checkphone(this.form.email); |
||||
let checke = checkEmail(this.form.email); |
||||
|
||||
if (this.allow_ways.sms && this.allow_ways.email) { |
||||
if (!checke && !checkp) { |
||||
this.$message({ |
||||
message: '请输入正确的邮箱地址或手机号码', |
||||
type: 'warning' |
||||
}); |
||||
return 0 |
||||
} |
||||
} else { |
||||
if (this.allow_ways.email) { |
||||
if (!checke) { |
||||
this.$message({ |
||||
message: '请输入正确的邮箱地址', |
||||
type: 'warning' |
||||
}); |
||||
return 0 |
||||
} |
||||
} |
||||
if (this.allow_ways.sms) { |
||||
if (!checkp) { |
||||
this.$message({ |
||||
message: '请输入正确的手机号码', |
||||
type: 'warning' |
||||
}); |
||||
return 0 |
||||
} |
||||
} |
||||
} |
||||
if (this.allow_ways.code && this.form.icode.length === 0) { |
||||
this.$message({ |
||||
message: '请输入邀请码', |
||||
type: 'warning' |
||||
}); |
||||
return 0 |
||||
} |
||||
return 1 |
||||
}, |
||||
do_register(params) { |
||||
registerFun(data => { |
||||
if (data.code === 1000) { |
||||
this.$message({ |
||||
message: '注册成功', |
||||
type: 'success' |
||||
}); |
||||
this.$router.push({name: 'FirLogin'}) |
||||
} else { |
||||
this.$message({ |
||||
message: data.msg, |
||||
type: 'error' |
||||
}); |
||||
this.get_auth_code(); |
||||
} |
||||
}, { |
||||
"methods": "POST", |
||||
"data": params |
||||
}); |
||||
this.register_disable = false; |
||||
}, |
||||
onRegist() { |
||||
let email = this.form.email; |
||||
let password = this.form.password; |
||||
let password2 = this.form.password2; |
||||
if (!this.docheck()) { |
||||
return |
||||
} |
||||
let authcode = this.form.authcode; |
||||
let cptch_flag = authcode.length === this.cptch.length; |
||||
if (this.cptch.cptch_key === '' || !this.cptch.cptch_key) { |
||||
cptch_flag = true |
||||
} |
||||
if (cptch_flag) { |
||||
if (password === password2 && password.length >= 6) { |
||||
let params = { |
||||
"username": email, |
||||
"password": password, |
||||
"password2": password2, |
||||
"auth_token": this.form.auth_token, |
||||
"auth_key": this.form.seicode |
||||
}; |
||||
this.register_disable = true; |
||||
if (this.cptch.geetest) { |
||||
geetest(this, params, (n_params) => { |
||||
this.do_register(n_params); |
||||
}) |
||||
} else { |
||||
this.do_register(params); |
||||
} |
||||
|
||||
} else { |
||||
this.$message({ |
||||
message: '密码不一致或者密码长度小于6', |
||||
type: 'warning' |
||||
}); |
||||
} |
||||
|
||||
} else { |
||||
this.$message({ |
||||
message: '验证码有误', |
||||
type: 'warning' |
||||
}); |
||||
} |
||||
|
||||
|
||||
}, |
||||
onLogin() { |
||||
this.$router.push({name: 'FirLogin'}) |
||||
}, |
||||
import {getAuthTokenFun, registerFun} from "@/restful"; |
||||
import {geetest} from "@/utils"; |
||||
import {checkEmail, checkphone} from "@/utils/base/utils"; |
||||
|
||||
export default { |
||||
name: "FirRegist", |
||||
data() { |
||||
return { |
||||
form: { |
||||
email: '', |
||||
password: '', |
||||
password2: '', |
||||
verify_code: '', |
||||
srccode: '', |
||||
seicode: '', |
||||
authtoken: '', |
||||
icode: '', |
||||
auth_token: '', |
||||
|
||||
}, |
||||
captcha: {"captcha_image": '', "captcha_key": '', "length": 8}, |
||||
auth_rules: {}, |
||||
allow_r: false, |
||||
allow_ways: {}, |
||||
rutitle: '', |
||||
register_disable: false, |
||||
} |
||||
}, |
||||
methods: { |
||||
set_rtitle() { |
||||
this.rutitle = ''; |
||||
if (this.allow_ways.sms) { |
||||
this.rutitle = this.rutitle + '手机号 '; |
||||
} |
||||
if (this.allow_ways.email) { |
||||
this.rutitle = this.rutitle + '邮箱 '; |
||||
} |
||||
|
||||
this.rutitle = this.rutitle.trim().replace(' ', '或'); |
||||
}, |
||||
get_auth_code() { |
||||
registerFun(data => { |
||||
if (data.code === 1000) { |
||||
let jdata = data.data; |
||||
if (jdata.enable) { |
||||
this.allow_r = true; |
||||
this.allow_ways = jdata.register_type; |
||||
this.form.verify_code = ''; |
||||
this.set_rtitle(); |
||||
this.auth_rules = data.data.auth_rules; |
||||
this.captcha = this.auth_rules.captcha; |
||||
} else { |
||||
this.allow_r = false; |
||||
this.$message({ |
||||
message: "该服务器不允许注册", |
||||
type: 'error' |
||||
}); |
||||
} |
||||
} else { |
||||
this.$message({ |
||||
message: data.msg, |
||||
type: 'error' |
||||
}); |
||||
} |
||||
, |
||||
created() { |
||||
}, mounted() { |
||||
this.get_auth_code(); |
||||
}, { |
||||
"methods": "GET", |
||||
"data": {} |
||||
}); |
||||
}, |
||||
do_get_auth_token(params) { |
||||
getAuthTokenFun(data => { |
||||
if (data.code === 1000) { |
||||
this.$notify({ |
||||
title: '验证码', |
||||
message: '您正在进行注册,验证码已经发送您', |
||||
type: 'success' |
||||
}); |
||||
this.form.auth_token = data.data.auth_token; |
||||
} else { |
||||
this.$message({ |
||||
message: data.msg, |
||||
type: 'error' |
||||
}); |
||||
} |
||||
} |
||||
}, {"methods": 'POST', 'data': params}) |
||||
}, |
||||
getphonecode() { |
||||
let act = 'up'; |
||||
if (!this.docheck()) { |
||||
return |
||||
} |
||||
if (checkphone(this.form.email)) { |
||||
act = 'sms' |
||||
} |
||||
if (checkEmail(this.form.email)) { |
||||
act = 'email' |
||||
} |
||||
let verify_code = this.form.verify_code; |
||||
let captcha_flag = verify_code.length === this.captcha.length; |
||||
if (this.captcha.captcha_key === '' || !this.captcha.captcha_key) { |
||||
captcha_flag = true |
||||
} |
||||
if (captcha_flag) { |
||||
let picode = { |
||||
"verify_code": verify_code, |
||||
"captcha_key": this.captcha.captcha_key, |
||||
"icode": this.form.icode, |
||||
}; |
||||
let params = {'act': act, 'target': this.form.email, 'ext': picode}; |
||||
if (this.auth_rules.geetest) { |
||||
geetest(this, this.form.email, params, (n_params) => { |
||||
this.do_get_auth_token(n_params); |
||||
}) |
||||
} else { |
||||
this.do_get_auth_token(params); |
||||
} |
||||
} else { |
||||
this.$message({ |
||||
message: '图片验证码有误', |
||||
type: 'warning' |
||||
}); |
||||
} |
||||
|
||||
}, |
||||
docheck() { |
||||
let checkp = checkphone(this.form.email); |
||||
let checke = checkEmail(this.form.email); |
||||
|
||||
if (this.allow_ways.sms && this.allow_ways.email) { |
||||
if (!checke && !checkp) { |
||||
this.$message({ |
||||
message: '请输入正确的邮箱地址或手机号码', |
||||
type: 'warning' |
||||
}); |
||||
return 0 |
||||
} |
||||
} else { |
||||
if (this.allow_ways.email) { |
||||
if (!checke) { |
||||
this.$message({ |
||||
message: '请输入正确的邮箱地址', |
||||
type: 'warning' |
||||
}); |
||||
return 0 |
||||
} |
||||
} |
||||
if (this.allow_ways.sms) { |
||||
if (!checkp) { |
||||
this.$message({ |
||||
message: '请输入正确的手机号码', |
||||
type: 'warning' |
||||
}); |
||||
return 0 |
||||
} |
||||
} |
||||
} |
||||
if (this.allow_ways.code && this.form.icode.length === 0) { |
||||
this.$message({ |
||||
message: '请输入邀请码', |
||||
type: 'warning' |
||||
}); |
||||
return 0 |
||||
} |
||||
return 1 |
||||
}, |
||||
do_register(params) { |
||||
registerFun(data => { |
||||
if (data.code === 1000) { |
||||
this.$message({ |
||||
message: '注册成功', |
||||
type: 'success' |
||||
}); |
||||
this.$router.push({name: 'FirLogin'}) |
||||
} else { |
||||
this.$message({ |
||||
message: data.msg, |
||||
type: 'error' |
||||
}); |
||||
this.get_auth_code(); |
||||
} |
||||
}, { |
||||
"methods": "POST", |
||||
"data": params |
||||
}); |
||||
this.register_disable = false; |
||||
}, |
||||
onRegist() { |
||||
let email = this.form.email; |
||||
let password = this.form.password; |
||||
let password2 = this.form.password2; |
||||
if (!this.docheck()) { |
||||
return |
||||
} |
||||
let verify_code = this.form.verify_code; |
||||
let captcha_flag = verify_code.length === this.captcha.length; |
||||
if (this.captcha.captcha_key === '' || !this.captcha.captcha_key) { |
||||
captcha_flag = true |
||||
} |
||||
if (captcha_flag) { |
||||
if (password === password2 && password.length >= 6) { |
||||
let params = { |
||||
"username": email, |
||||
"password": password, |
||||
"password2": password2, |
||||
"auth_token": this.form.auth_token, |
||||
"auth_key": this.form.seicode |
||||
}; |
||||
this.register_disable = true; |
||||
if (this.auth_rules.geetest) { |
||||
geetest(this, this.form.email, params, (n_params) => { |
||||
this.do_register(n_params); |
||||
}) |
||||
} else { |
||||
this.do_register(params); |
||||
} |
||||
|
||||
} else { |
||||
this.$message({ |
||||
message: '密码不一致或者密码长度小于6', |
||||
type: 'warning' |
||||
}); |
||||
} |
||||
|
||||
} else { |
||||
this.$message({ |
||||
message: '验证码有误', |
||||
type: 'warning' |
||||
}); |
||||
} |
||||
|
||||
|
||||
}, |
||||
onLogin() { |
||||
this.$router.push({name: 'FirLogin'}) |
||||
}, |
||||
} |
||||
, |
||||
created() { |
||||
}, mounted() { |
||||
this.get_auth_code(); |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style scoped> |
||||
|
||||
.el-container { |
||||
margin: 10px auto; |
||||
width: 1266px; |
||||
|
||||
} |
||||
|
||||
.el-header { |
||||
margin-top: 13%; |
||||
} |
||||
|
||||
.el-form { |
||||
max-width: 360px; |
||||
margin: 0 auto; |
||||
} |
||||
|
||||
.el-form-item .el-button { |
||||
max-width: 360px; |
||||
width: 100%; |
||||
position: relative; |
||||
height: 50px; |
||||
|
||||
} |
||||
|
||||
.el-header { |
||||
text-align: center; |
||||
overflow: hidden; |
||||
margin-bottom: 50px |
||||
} |
||||
|
||||
|
||||
.el-header div span { |
||||
font-size: 24px; |
||||
display: inline-block; |
||||
vertical-align: middle; |
||||
padding: 8px 40px |
||||
} |
||||
|
||||
.el-header div:before, .el-header div:after { |
||||
content: ' '; |
||||
display: inline-block; |
||||
vertical-align: middle; |
||||
width: 50%; |
||||
height: 1px; |
||||
background-color: #babfc3; |
||||
margin: 0 0 0 -50% |
||||
} |
||||
|
||||
.el-header div { |
||||
text-align: center |
||||
} |
||||
|
||||
.el-header div:after { |
||||
margin: 0 -50% 0 0 |
||||
} |
||||
.el-container { |
||||
margin: 10px auto; |
||||
width: 1266px; |
||||
|
||||
} |
||||
|
||||
.el-header { |
||||
margin-top: 13%; |
||||
} |
||||
|
||||
.el-form { |
||||
max-width: 360px; |
||||
margin: 0 auto; |
||||
} |
||||
|
||||
.el-form-item .el-button { |
||||
max-width: 360px; |
||||
width: 100%; |
||||
position: relative; |
||||
height: 50px; |
||||
|
||||
} |
||||
|
||||
.el-header { |
||||
text-align: center; |
||||
overflow: hidden; |
||||
margin-bottom: 50px |
||||
} |
||||
|
||||
|
||||
.el-header div span { |
||||
font-size: 24px; |
||||
display: inline-block; |
||||
vertical-align: middle; |
||||
padding: 8px 40px |
||||
} |
||||
|
||||
.el-header div:before, .el-header div:after { |
||||
content: ' '; |
||||
display: inline-block; |
||||
vertical-align: middle; |
||||
width: 50%; |
||||
height: 1px; |
||||
background-color: #babfc3; |
||||
margin: 0 0 0 -50% |
||||
} |
||||
|
||||
.el-header div { |
||||
text-align: center |
||||
} |
||||
|
||||
.el-header div:after { |
||||
margin: 0 -50% 0 0 |
||||
} |
||||
|
||||
|
||||
</style> |
||||
|
@ -1,235 +1,280 @@ |
||||
<template> |
||||
<el-container> |
||||
<div style="margin: 10px 0 10px 0 ;position:absolute;right:20px;top:auto;"> |
||||
<el-button round icon="el-icon-arrow-left" @click="$router.go(-1)"/> |
||||
<el-button round icon="el-icon-s-home" @click="$router.push({name:'FirIndex'})"/> |
||||
|
||||
</div> |
||||
<el-header> |
||||
<div> |
||||
<span>忘记密码</span> |
||||
</div> |
||||
|
||||
</el-header> |
||||
<el-main> |
||||
<el-form ref="form" :model="form"> |
||||
<el-form-item> |
||||
<el-input v-model="form.email" prefix-icon="el-icon-user" placeholder="邮箱" autofocus |
||||
clearable/> |
||||
</el-form-item> |
||||
<el-form-item style="height: 40px" v-if="cptch.cptch_image"> |
||||
<el-row style="height: 40px"> |
||||
<el-col :span="16"> |
||||
<el-input placeholder="请输入验证码" v-model="form.authcode" maxlength="6" |
||||
@keyup.enter.native="onSubmit" clearable/> |
||||
</el-col> |
||||
<el-col :span="8"> |
||||
<el-image |
||||
style="margin:0 4px;border-radius:4px;cursor:pointer;height: 40px" |
||||
:src="cptch.cptch_image" |
||||
fit="contain" @click="get_auth_code"> |
||||
</el-image> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
|
||||
<el-form-item> |
||||
<div id="captcha" ref="captcha"></div> |
||||
</el-form-item> |
||||
<el-form-item style="margin-top: 30px"> |
||||
<el-button type="danger" :disabled="login_disable" @click="onSubmit">发送重置密码邮件</el-button> |
||||
</el-form-item> |
||||
<el-form-item style="margin-top: 30px"> |
||||
<el-button type="primary" @click="onLogin">我是老用户,要登录</el-button> |
||||
</el-form-item> |
||||
<el-form-item v-if="register_enable" style="margin-top: 30px"> |
||||
<el-button type="primary" @click="onRegister" plain>注册</el-button> |
||||
</el-form-item> |
||||
|
||||
</el-form> |
||||
|
||||
|
||||
</el-main> |
||||
|
||||
|
||||
</el-container> |
||||
<el-container> |
||||
<div style="margin: 10px 0 10px 0 ;position:absolute;right:20px;top:auto;"> |
||||
<el-button icon="el-icon-arrow-left" round @click="$router.go(-1)"/> |
||||
<el-button icon="el-icon-s-home" round @click="$router.push({name:'FirIndex'})"/> |
||||
|
||||
</div> |
||||
<el-header> |
||||
<div> |
||||
<span>忘记密码</span> |
||||
</div> |
||||
|
||||
</el-header> |
||||
<el-main> |
||||
<el-form ref="form" :model="form"> |
||||
<el-form-item> |
||||
<el-input v-model="form.email" autofocus clearable placeholder="邮箱或手机号" |
||||
prefix-icon="el-icon-user"/> |
||||
</el-form-item> |
||||
<el-form-item v-if="captcha.captcha_image" style="height: 40px"> |
||||
<el-row style="height: 40px"> |
||||
<el-col :span="16"> |
||||
<el-input v-model="form.verify_code" clearable maxlength="6" |
||||
placeholder="请输入验证码" @keyup.enter.native="onSubmit"/> |
||||
</el-col> |
||||
<el-col :span="8"> |
||||
<el-image |
||||
:src="captcha.captcha_image" |
||||
fit="contain" |
||||
style="margin:0 4px;border-radius:4px;cursor:pointer;height: 40px" @click="get_auth_code"> |
||||
</el-image> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
|
||||
<el-form-item> |
||||
<el-row> |
||||
<el-col :span="16"> |
||||
<el-input v-model="form.seicode" clearable |
||||
placeholder="验证码" prefix-icon="el-icon-mobile"/> |
||||
</el-col> |
||||
<el-col :span="8"> |
||||
<el-button plain style="margin:0 4px;border-radius:4px;cursor:pointer;height: 40px" type="info" |
||||
@click="onGetCode">获取验证码 |
||||
</el-button> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
|
||||
<el-form-item> |
||||
<div id="captcha" ref="captcha"></div> |
||||
</el-form-item> |
||||
<el-form-item style="margin-top: 30px"> |
||||
<el-button :disabled="login_disable" type="danger" @click="onReset">发送重置密码邮件</el-button> |
||||
</el-form-item> |
||||
<el-form-item style="margin-top: 30px"> |
||||
<el-button type="primary" @click="onLogin">我是老用户,要登录</el-button> |
||||
</el-form-item> |
||||
<el-form-item v-if="register_enable" style="margin-top: 30px"> |
||||
<el-button plain type="primary" @click="onRegister">注册</el-button> |
||||
</el-form-item> |
||||
|
||||
</el-form> |
||||
|
||||
|
||||
</el-main> |
||||
|
||||
|
||||
</el-container> |
||||
|
||||
</template> |
||||
|
||||
<script> |
||||
import {loginFun} from "@/restful"; |
||||
import {checkEmail, geetest} from "@/utils"; |
||||
|
||||
export default { |
||||
name: "FirResetPwd", |
||||
data() { |
||||
return { |
||||
form: { |
||||
email: '', |
||||
password: '', |
||||
authcode: '' |
||||
}, |
||||
cptch: {"cptch_image": '', "cptch_key": '', "length": 8}, |
||||
activeName: 'username', |
||||
allow_ways: {}, |
||||
rutitle: '', |
||||
rctitle: '', |
||||
register_enable: false, |
||||
login_disable: false, |
||||
} |
||||
}, |
||||
methods: { |
||||
is_cptch() { |
||||
let cptch_flag = this.form.authcode.length === this.cptch.length; |
||||
if (this.cptch.cptch_key === '' || !this.cptch.cptch_key) { |
||||
cptch_flag = true |
||||
} |
||||
return cptch_flag |
||||
}, |
||||
onSubmit() { |
||||
let email = this.form.email; |
||||
let authcode = this.form.authcode; |
||||
let cptch_flag = this.form.authcode.length === this.cptch.length; |
||||
if (this.cptch.cptch_key === '' || !this.cptch.cptch_key) { |
||||
cptch_flag = true |
||||
} |
||||
if (cptch_flag) { |
||||
let checke = checkEmail(this.form.email); |
||||
if (!checke) { |
||||
this.$message({ |
||||
message: '邮箱输入有误', |
||||
type: 'error' |
||||
}); |
||||
return |
||||
} |
||||
let params = { |
||||
"username": email, |
||||
"authcode": authcode, |
||||
"cptch_key": this.cptch.cptch_key, |
||||
"login_type": 'reset', |
||||
}; |
||||
this.login_disable = true; |
||||
if (this.cptch.geetest) { |
||||
geetest(this, params, (n_params) => { |
||||
this.do_login(n_params); |
||||
}) |
||||
} else { |
||||
this.do_login(params) |
||||
} |
||||
|
||||
} else { |
||||
this.$message({ |
||||
message: '验证码有误', |
||||
type: 'warning' |
||||
}); |
||||
} |
||||
}, |
||||
do_login(params) { |
||||
loginFun(data => { |
||||
if (data.code === 1000) { |
||||
this.$message({ |
||||
message: '密码重置成功,请登录邮箱查看邮件', |
||||
type: 'success' |
||||
}); |
||||
|
||||
} else { |
||||
this.$message({ |
||||
message: data.msg, |
||||
type: 'error' |
||||
}); |
||||
this.get_auth_code(); |
||||
} |
||||
this.login_disable = false; |
||||
}, { |
||||
"methods": "POST", |
||||
"data": params |
||||
}); |
||||
}, |
||||
onRegister() { |
||||
this.$router.push({name: 'FirRegist'}) |
||||
}, |
||||
onLogin() { |
||||
this.$router.push({name: 'FirLogin'}) |
||||
}, |
||||
get_auth_code() { |
||||
loginFun(data => { |
||||
if (data.code === 1000) { |
||||
this.cptch = data.data; |
||||
this.register_enable = data.data.register_enable; |
||||
this.form.authcode = ''; |
||||
} else { |
||||
this.$message({ |
||||
message: data.msg, |
||||
type: 'error' |
||||
}); |
||||
} |
||||
}, { |
||||
"methods": "GET", |
||||
"data": {} |
||||
}); |
||||
}, |
||||
}, |
||||
mounted() { |
||||
this.get_auth_code(); |
||||
}, created() { |
||||
} |
||||
import {loginFun} from "@/restful"; |
||||
import {geetest} from "@/utils"; |
||||
import {checkEmail, checkphone} from "@/utils/base/utils"; |
||||
|
||||
export default { |
||||
name: "FirResetPwd", |
||||
data() { |
||||
return { |
||||
form: { |
||||
email: '', |
||||
password: '', |
||||
verify_code: '', |
||||
seicode: '', |
||||
auth_token: '' |
||||
}, |
||||
captcha: {"captcha_image": '', "captcha_key": '', "length": 8}, |
||||
auth_rules: {}, |
||||
activeName: 'username', |
||||
allow_ways: {}, |
||||
rutitle: '', |
||||
rctitle: '', |
||||
register_enable: false, |
||||
login_disable: false, |
||||
} |
||||
}, |
||||
methods: { |
||||
onGetCode() { |
||||
this.form.auth_token = ''; |
||||
this.form.seicode = ''; |
||||
this.onSubmit(); |
||||
}, |
||||
onReset() { |
||||
if (this.form.auth_token && this.form.seicode && this.form.seicode.length > 3) { |
||||
this.onSubmit() |
||||
} else { |
||||
this.$message.error("输入有误,请检查") |
||||
} |
||||
}, |
||||
is_captcha() { |
||||
let captcha_flag = this.form.verify_code.length === this.captcha.length; |
||||
if (this.captcha.captcha_key === '' || !this.captcha.captcha_key) { |
||||
captcha_flag = true |
||||
} |
||||
return captcha_flag |
||||
}, |
||||
onSubmit() { |
||||
let email = this.form.email; |
||||
let verify_code = this.form.verify_code; |
||||
let captcha_flag = this.form.verify_code.length === this.captcha.length; |
||||
if (this.captcha.captcha_key === '' || !this.captcha.captcha_key) { |
||||
captcha_flag = true |
||||
} |
||||
if (captcha_flag) { |
||||
let checke = checkEmail(this.form.email); |
||||
let checkp = checkphone(this.form.email); |
||||
if (checke || checkp) { |
||||
let params = { |
||||
"username": email, |
||||
"verify_code": verify_code, |
||||
"captcha_key": this.captcha.captcha_key, |
||||
"login_type": 'reset', |
||||
}; |
||||
let seicode = this.form.seicode; |
||||
let auth_token = this.form.auth_token; |
||||
if (seicode && seicode.length > 3) { |
||||
params['seicode'] = seicode |
||||
} |
||||
if (auth_token && auth_token.length > 3) { |
||||
params['auth_token'] = auth_token |
||||
} |
||||
this.login_disable = true; |
||||
if (this.auth_rules.geetest) { |
||||
geetest(this, this.form.email, params, (n_params) => { |
||||
this.do_login(n_params); |
||||
}) |
||||
} else { |
||||
this.do_login(params) |
||||
} |
||||
} else { |
||||
this.$message({ |
||||
message: '邮箱或手机号输入有误', |
||||
type: 'error' |
||||
}); |
||||
} |
||||
|
||||
} else { |
||||
this.$message({ |
||||
message: '验证码有误', |
||||
type: 'warning' |
||||
}); |
||||
} |
||||
}, |
||||
do_login(params) { |
||||
loginFun(data => { |
||||
if (data.code === 1000) { |
||||
let msg = '密码重置成功,请登录邮箱或者手机短信查看'; |
||||
if (data.data && data.data.auth_token) { |
||||
this.form.auth_token = data.data.auth_token; |
||||
msg = "验证码发送成功,请登录邮箱或者手机短信查看" |
||||
} |
||||
this.$message({ |
||||
message: msg, |
||||
type: 'success' |
||||
}); |
||||
|
||||
} else { |
||||
this.$message({ |
||||
message: data.msg, |
||||
type: 'error' |
||||
}); |
||||
this.get_auth_code(); |
||||
} |
||||
this.login_disable = false; |
||||
}, { |
||||
"methods": "POST", |
||||
"data": params |
||||
}); |
||||
}, |
||||
onRegister() { |
||||
this.$router.push({name: 'FirRegist'}) |
||||
}, |
||||
onLogin() { |
||||
this.$router.push({name: 'FirLogin'}) |
||||
}, |
||||
get_auth_code() { |
||||
loginFun(data => { |
||||
if (data.code === 1000) { |
||||
this.auth_rules = data.data.auth_rules; |
||||
this.captcha = this.auth_rules.captcha; |
||||
this.register_enable = data.data.register_enable; |
||||
this.form.verify_code = ''; |
||||
} else { |
||||
this.$message({ |
||||
message: data.msg, |
||||
type: 'error' |
||||
}); |
||||
} |
||||
}, { |
||||
"methods": "GET", |
||||
"data": {} |
||||
}); |
||||
}, |
||||
}, |
||||
mounted() { |
||||
this.get_auth_code(); |
||||
}, created() { |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style scoped> |
||||
|
||||
.el-container { |
||||
margin: 10px auto; |
||||
width: 1266px; |
||||
} |
||||
.el-container { |
||||
margin: 10px auto; |
||||
width: 1266px; |
||||
} |
||||
|
||||
.el-header { |
||||
margin-top: 13%; |
||||
} |
||||
.el-header { |
||||
margin-top: 13%; |
||||
} |
||||
|
||||
.el-form { |
||||
max-width: 360px; |
||||
margin: 0 auto; |
||||
} |
||||
.el-form { |
||||
max-width: 360px; |
||||
margin: 0 auto; |
||||
} |
||||
|
||||
.el-form-item .el-button { |
||||
max-width: 360px; |
||||
/*padding: 16px 20px;*/ |
||||
width: 100%; |
||||
position: relative; |
||||
height: 50px; |
||||
.el-form-item .el-button { |
||||
max-width: 360px; |
||||
/*padding: 16px 20px;*/ |
||||
width: 100%; |
||||
position: relative; |
||||
height: 50px; |
||||
|
||||
} |
||||
} |
||||
|
||||
.el-header { |
||||
text-align: center; |
||||
overflow: hidden; |
||||
margin-bottom: 50px |
||||
} |
||||
.el-header { |
||||
text-align: center; |
||||
overflow: hidden; |
||||
margin-bottom: 50px |
||||
} |
||||
|
||||
|
||||
.el-header div span { |
||||
font-size: 24px; |
||||
display: inline-block; |
||||
vertical-align: middle; |
||||
padding: 8px 40px |
||||
} |
||||
.el-header div span { |
||||
font-size: 24px; |
||||
display: inline-block; |
||||
vertical-align: middle; |
||||
padding: 8px 40px |
||||
} |
||||
|
||||
.el-header div:before, .el-header div:after { |
||||
content: ' '; |
||||
display: inline-block; |
||||
vertical-align: middle; |
||||
width: 50%; |
||||
height: 1px; |
||||
background-color: #babfc3; |
||||
margin: 0 0 0 -50% |
||||
} |
||||
.el-header div:before, .el-header div:after { |
||||
content: ' '; |
||||
display: inline-block; |
||||
vertical-align: middle; |
||||
width: 50%; |
||||
height: 1px; |
||||
background-color: #babfc3; |
||||
margin: 0 0 0 -50% |
||||
} |
||||
|
||||
.el-header div { |
||||
text-align: center |
||||
} |
||||
.el-header div { |
||||
text-align: center |
||||
} |
||||
|
||||
.el-header div:after { |
||||
margin: 0 -50% 0 0 |
||||
} |
||||
.el-header div:after { |
||||
margin: 0 -50% 0 0 |
||||
} |
||||
</style> |
||||
|
@ -1,395 +1,395 @@ |
||||
<template> |
||||
<div class="main"> |
||||
<div class="page-app app-info"> |
||||
<div class="banner"> |
||||
<div class="middle-wrapper"> |
||||
<div @click="defaulttimeline"> |
||||
<img ref="icon_url" :src="icon_url" class="appicon" style="width:100px; height:100px" alt=""> |
||||
</div> |
||||
<div class="badges"> |
||||
<el-tooltip content="复制到剪切板" placement="top"> |
||||
<span class="bundleid short" |
||||
v-clipboard:copy="short_full_url" |
||||
<div class="main"> |
||||
<div class="page-app app-info"> |
||||
<div class="banner"> |
||||
<div class="middle-wrapper"> |
||||
<div @click="defaulttimeline"> |
||||
<img ref="icon_url" :src="icon_url" alt="" class="appicon" style="width:100px; height:100px"> |
||||
</div> |
||||
<div class="badges"> |
||||
<el-tooltip content="复制到剪切板" placement="top"> |
||||
<span v-clipboard:copy="appinfos.preview_url" |
||||
v-clipboard:success="copy_success" |
||||
> {{short_full_url }}</span> |
||||
</el-tooltip> |
||||
<span>{{ master_release.release_type |getapptype }}</span> |
||||
<el-tooltip content="下载量" placement="top"> |
||||
<span><i class="el-icon-cloudy"/><b class="short">{{ appinfos.count_hits }}</b></span> |
||||
</el-tooltip> |
||||
<span class="bundleid ng-binding">BundleID<b class="ng-binding"> {{ appinfos.bundle_id }}</b></span> |
||||
<span class="version ng-scope">{{ master_release.minimum_os_version }} 或者高版本</span> |
||||
<span class="short ng-scope" v-if="appinfos.issupersign">超级签</span> |
||||
|
||||
<el-popover v-if="$store.state.userinfo.role === 3" |
||||
placement="right" |
||||
width="288"> |
||||
<div style="text-align: center; margin: 0"> |
||||
<vue-qr :margin="qrinfo.margin" |
||||
:logoSrc="icon_url" :logoScale="qrinfo.logoScale" |
||||
:logoCornerRadius="qrinfo.logoCornerRadius" |
||||
:correctLevel="qrinfo.correctLevel" |
||||
:text="short_url()" :size="266" |
||||
ref="qr"> |
||||
</vue-qr> |
||||
<el-button type="primary" size="small" @click="save_qr()">保存本地</el-button> |
||||
</div> |
||||
|
||||
<span class="short ng-scope" slot="reference">下载码</span> |
||||
</el-popover> |
||||
|
||||
|
||||
</div> |
||||
<div class="actions"> |
||||
<el-button v-if="appinfos.status!==1" type="danger">该应用被封禁,请联系管理员</el-button> |
||||
<el-button v-else @click="appDownload" class="download" icon="el-icon-view"> |
||||
预览 |
||||
</el-button> |
||||
</div> |
||||
|
||||
<div class="tabs-container"> |
||||
<el-row :gutter="1"> |
||||
<el-col :span="3"> |
||||
<a class="" ref="baseinfo" @click="baseinfo"><i class="el-icon-document"/>基本信息</a> |
||||
</el-col> |
||||
|
||||
<el-col :span="3"> |
||||
<a class="" ref="security" @click="security"><i class="el-icon-set-up"/>应用管理</a> |
||||
</el-col> |
||||
|
||||
<el-col :span="3"> |
||||
<a class="" ref="combo" @click="combo"><i class="el-icon-copy-document" |
||||
style="transform:rotateX(180deg);"/>应用合并</a> |
||||
</el-col> |
||||
|
||||
<el-col :span="3" |
||||
v-if="appinfos.type===1 || appinfos.issupersign "> |
||||
<a class="" ref="supersign" @click="supersign"><i |
||||
class="el-icon-ship"/>超级签名</a> |
||||
</el-col> |
||||
|
||||
<el-col :span="3" |
||||
v-if="(appinfos.type===1 && master_release.release_type ===1) || appinfos.issupersign "> |
||||
<a class="" ref="devices" @click="devices"><i class="el-icon-mobile-phone"/>设备列表</a> |
||||
</el-col> |
||||
|
||||
</el-row> |
||||
</div> |
||||
class="bundleid short" |
||||
> {{ appinfos.preview_url }}</span> |
||||
</el-tooltip> |
||||
<el-tooltip content="点击查看下载码"> |
||||
|
||||
<el-popover |
||||
placement="right" |
||||
width="288"> |
||||
<div style="text-align: center; margin: 0"> |
||||
<vue-qr ref="qr" |
||||
:correctLevel="qrinfo.correctLevel" :logoCornerRadius="qrinfo.logoCornerRadius" |
||||
:logoScale="qrinfo.logoScale" |
||||
:logoSrc="icon_url" |
||||
:margin="qrinfo.margin" :size="266" |
||||
:text="appinfos.preview_url"> |
||||
</vue-qr> |
||||
<el-button size="small" type="primary" @click="save_qr()">保存本地</el-button> |
||||
</div> |
||||
</div> |
||||
|
||||
<div> |
||||
<div class="block" style="margin-top: -46px;color: #d5f9f9"> |
||||
<el-slider |
||||
v-model="$store.state.appInfoIndex[0]" |
||||
range |
||||
:show-tooltip="false" |
||||
:max="100"> |
||||
</el-slider> |
||||
</div> |
||||
<el-container style="padding-top: 20px;max-width: 96%"> |
||||
<router-view/> |
||||
</el-container> |
||||
</div> |
||||
<span slot="reference" class="short ng-scope">下载码</span> |
||||
</el-popover> |
||||
</el-tooltip> |
||||
|
||||
|
||||
<span>{{ master_release.release_type |getapptype }}</span> |
||||
<el-tooltip placement="top"> |
||||
<div slot="content">总下载次数:{{ appinfos.count_hits }}<br/>当天下载次数:{{ appinfos.today_hits_count }}</div> |
||||
<span><i class="el-icon-cloudy"/><b class="short">{{ |
||||
appinfos.count_hits |
||||
}} | {{ appinfos.today_hits_count }} </b></span> |
||||
</el-tooltip> |
||||
<span class="bundleid ng-binding">BundleID<b class="ng-binding"> |
||||
<el-tooltip content="复制到剪切板" placement="top"> |
||||
<span v-clipboard:copy="appinfos.bundle_id" |
||||
v-clipboard:success="copy_success" |
||||
class="bundleid short" |
||||
> {{ appinfos.bundle_id }}</span> |
||||
</el-tooltip> |
||||
</b></span> |
||||
<span class="version ng-scope">{{ master_release.minimum_os_version }} 或者高版本</span> |
||||
<span v-if="appinfos.issupersign" class="short ng-scope">超级签</span> |
||||
|
||||
</div> |
||||
<div class="actions"> |
||||
<el-button v-if="appinfos.status!==1" type="danger">该应用被封禁,请联系管理员</el-button> |
||||
<el-button v-else class="download" icon="el-icon-view" @click="appDownload(appinfos)"> |
||||
预览 |
||||
</el-button> |
||||
</div> |
||||
|
||||
<div class="tabs-container"> |
||||
<el-row :gutter="1"> |
||||
<el-col :span="3"> |
||||
<a ref="baseinfo" class="" @click="baseinfo"><i class="el-icon-document"/>基本信息</a> |
||||
</el-col> |
||||
|
||||
<el-col :span="3"> |
||||
<a ref="security" class="" @click="security"><i class="el-icon-set-up"/>应用管理</a> |
||||
</el-col> |
||||
|
||||
<el-col :span="3"> |
||||
<a ref="combo" class="" @click="combo"><i class="el-icon-copy-document" |
||||
style="transform:rotateX(180deg);"/>应用合并</a> |
||||
</el-col> |
||||
|
||||
<el-col v-if="appinfos.type===1 || appinfos.issupersign " |
||||
:span="3"> |
||||
<a ref="supersign" class="" @click="supersign"><i |
||||
class="el-icon-ship"/>超级签名</a> |
||||
</el-col> |
||||
|
||||
<el-col v-if="(appinfos.type===1 && master_release.release_type ===1) || appinfos.issupersign " |
||||
:span="3"> |
||||
<a ref="devices" class="" @click="devices"><i class="el-icon-mobile-phone"/>设备列表</a> |
||||
</el-col> |
||||
|
||||
</el-row> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
<div> |
||||
<div class="block" style="margin-top: -46px;color: #d5f9f9"> |
||||
<el-slider |
||||
v-model="$store.state.appInfoIndex[0]" |
||||
:max="100" |
||||
:show-tooltip="false" |
||||
range> |
||||
</el-slider> |
||||
</div> |
||||
<el-container style="padding-top: 20px;max-width: 96%"> |
||||
<router-view/> |
||||
</el-container> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
</template> |
||||
|
||||
<script> |
||||
import {apputils} from "@/restful"; |
||||
import VueQr from 'vue-qr'; |
||||
import {getUserInfoFun} from "@/utils"; |
||||
|
||||
export default { |
||||
name: "FirAppInfosBase", |
||||
components: { |
||||
VueQr |
||||
}, |
||||
data() { |
||||
return { |
||||
qrinfo: { |
||||
logoScale: 0.3, |
||||
logoCornerRadius: 12, |
||||
correctLevel: 3, |
||||
margin: 20 |
||||
}, |
||||
icon_url: "", |
||||
appinfos: {status: 1}, |
||||
master_release: {}, |
||||
allapp: [], |
||||
activity: { |
||||
editing: false |
||||
}, |
||||
short_full_url: '', |
||||
} |
||||
}, |
||||
methods: { |
||||
copy_success() { |
||||
this.$message.success('复制剪切板成功'); |
||||
}, |
||||
save_qr() { |
||||
let dtype = "I"; |
||||
if (this.master_release.release_type === 0) { |
||||
dtype = "A"; |
||||
} |
||||
let a = document.createElement('a'); |
||||
// 下载图名字 |
||||
a.download = this.appinfos.name + '_' + dtype + "_下载码"; |
||||
//url |
||||
a.href = this.$refs.qr.$el.src; |
||||
//合成函数,执行下载 |
||||
a.dispatchEvent(new MouseEvent('click')) |
||||
}, |
||||
short_url() { |
||||
return location.origin + '/' + this.appinfos.short; |
||||
}, |
||||
setfunactive(item, index) { |
||||
for (let key in this.$refs) { |
||||
if (key === "qr") continue; |
||||
if (key === item) { |
||||
if (this.$refs[key]) { |
||||
this.$refs[key].classList.add('active'); |
||||
this.$store.dispatch('doappInfoIndex', [[index, index], [index, index]]); |
||||
} |
||||
} else { |
||||
if (this.$refs[key]) { |
||||
this.$refs[key].classList.remove('active'); |
||||
} |
||||
} |
||||
} |
||||
}, |
||||
appDownload() { |
||||
let routeData = this.$router.resolve({name: 'FirDownload', params: {short: this.appinfos.short}}); |
||||
// window.open(routeData.href, '_blank'); |
||||
let p_url = routeData.href; |
||||
// let p_url = location.origin + '/' + this.appinfos.short; |
||||
if (this.appinfos.preview_url && this.appinfos.preview_url.length > 6) { |
||||
p_url = this.appinfos.preview_url + p_url |
||||
} |
||||
window.open(p_url, '_blank', ''); |
||||
}, |
||||
defaulttimeline() { |
||||
this.setfunactive('timeline', 5); |
||||
this.$router.push({name: 'FirAppInfostimeline'}); |
||||
}, |
||||
baseinfo() { |
||||
this.setfunactive('baseinfo', 18); |
||||
this.$router.push({name: 'FirAppInfosbaseinfo'}); |
||||
}, |
||||
security() { |
||||
this.setfunactive('security', 31); |
||||
this.$router.push({name: 'FirAppInfossecurity'}); |
||||
|
||||
}, |
||||
combo() { |
||||
this.setfunactive('combo', 44); |
||||
this.$router.push({name: 'FirAppInfoscombo'}); |
||||
}, |
||||
devices() { |
||||
this.setfunactive('devices', 70); |
||||
this.$router.push({name: 'FirAppInfosdevices'}); |
||||
}, |
||||
supersign() { |
||||
this.setfunactive('supersign', 57); |
||||
this.$router.push({name: 'FirAppInfossupersign'}); |
||||
}, |
||||
set_icon_url() { |
||||
this.icon_url = this.$store.state.currentapp.master_release.icon_url; |
||||
}, |
||||
}, created() { |
||||
|
||||
}, filters: { |
||||
getapptype: function (type) { |
||||
let ftype = ''; |
||||
if (type === 0) { |
||||
ftype = 'Android' |
||||
} else { |
||||
ftype = 'iOS' |
||||
} |
||||
return ftype |
||||
}, |
||||
}, |
||||
computed: {}, mounted() { |
||||
getUserInfoFun(this); |
||||
apputils(data => { |
||||
if (data.code === 1000) { |
||||
this.appinfos = data.data; |
||||
this.master_release = data.data.master_release; |
||||
this.appinfos["icon_url"] = this.master_release.icon_url; |
||||
this.$store.dispatch('doucurrentapp', this.appinfos); |
||||
this.short_full_url = this.appinfos.preview_url + "/" + this.appinfos.short; |
||||
} else if (data.code === 1003) { |
||||
this.$router.push({name: 'FirApps'}); |
||||
} else { |
||||
// eslint-disable-next-line no-console |
||||
console.log("Error"); |
||||
} |
||||
}, { |
||||
"methods": "GET", |
||||
"app_id": this.$route.params.id |
||||
}); |
||||
if (this.$store.state.currentapp.master_release) { |
||||
this.set_icon_url() |
||||
} |
||||
}, watch: { |
||||
'$store.state.currentapp.master_release.icon_url': function () { |
||||
this.set_icon_url() |
||||
}, |
||||
'$store.state.currentapp': function () { |
||||
this.appinfos = this.$store.state.currentapp; |
||||
}, |
||||
}, destroyed() { |
||||
this.$store.dispatch('doucurrentapp', {}); |
||||
import {apputils} from "@/restful"; |
||||
import VueQr from 'vue-qr'; |
||||
import {getUserInfoFun} from "@/utils"; |
||||
|
||||
export default { |
||||
name: "FirAppInfosBase", |
||||
components: { |
||||
VueQr |
||||
}, |
||||
data() { |
||||
return { |
||||
qrinfo: { |
||||
logoScale: 0.3, |
||||
logoCornerRadius: 12, |
||||
correctLevel: 3, |
||||
margin: 20 |
||||
}, |
||||
icon_url: "", |
||||
appinfos: {status: 1, preview_url: ''}, |
||||
master_release: {}, |
||||
allapp: [], |
||||
activity: { |
||||
editing: false |
||||
}, |
||||
} |
||||
}, |
||||
methods: { |
||||
copy_success() { |
||||
this.$message.success('复制剪切板成功'); |
||||
}, |
||||
save_qr() { |
||||
let dtype = "I"; |
||||
if (this.master_release.release_type === 0) { |
||||
dtype = "A"; |
||||
} |
||||
let a = document.createElement('a'); |
||||
// 下载图名字 |
||||
a.download = this.appinfos.name + '_' + dtype + "_下载码"; |
||||
//url |
||||
a.href = this.$refs.qr.$el.src; |
||||
//合成函数,执行下载 |
||||
a.dispatchEvent(new MouseEvent('click')) |
||||
}, |
||||
setfunactive(item, index) { |
||||
for (let key in this.$refs) { |
||||
if (key === "qr") continue; |
||||
if (key === item) { |
||||
if (this.$refs[key]) { |
||||
this.$refs[key].classList.add('active'); |
||||
this.$store.dispatch('doappInfoIndex', [[index, index], [index, index]]); |
||||
} |
||||
} else { |
||||
if (this.$refs[key]) { |
||||
this.$refs[key].classList.remove('active'); |
||||
} |
||||
} |
||||
|
||||
} |
||||
}, |
||||
appDownload(appinfo) { |
||||
window.open(appinfo.preview_url, '_blank', ''); |
||||
}, |
||||
defaulttimeline() { |
||||
this.setfunactive('timeline', 5); |
||||
this.$router.push({name: 'FirAppInfostimeline'}); |
||||
}, |
||||
baseinfo() { |
||||
this.setfunactive('baseinfo', 18); |
||||
this.$router.push({name: 'FirAppInfosbaseinfo'}); |
||||
}, |
||||
security() { |
||||
this.setfunactive('security', 31); |
||||
this.$router.push({name: 'FirAppInfossecurity'}); |
||||
|
||||
}, |
||||
combo() { |
||||
this.setfunactive('combo', 44); |
||||
this.$router.push({name: 'FirAppInfoscombo'}); |
||||
}, |
||||
devices() { |
||||
this.setfunactive('devices', 70); |
||||
this.$router.push({name: 'FirAppInfosdevices'}); |
||||
}, |
||||
supersign() { |
||||
this.setfunactive('supersign', 57); |
||||
this.$router.push({name: 'FirAppInfossupersign'}); |
||||
}, |
||||
set_icon_url() { |
||||
this.icon_url = this.$store.state.currentapp.master_release.icon_url; |
||||
}, |
||||
}, created() { |
||||
|
||||
}, filters: { |
||||
getapptype: function (type) { |
||||
let ftype = ''; |
||||
if (type === 0) { |
||||
ftype = 'Android' |
||||
} else { |
||||
ftype = 'iOS' |
||||
} |
||||
return ftype |
||||
}, |
||||
}, |
||||
computed: {}, mounted() { |
||||
getUserInfoFun(this); |
||||
apputils(data => { |
||||
if (data.code === 1000) { |
||||
this.appinfos = data.data; |
||||
this.master_release = data.data.master_release; |
||||
this.appinfos["icon_url"] = this.master_release.icon_url; |
||||
this.$store.dispatch('doucurrentapp', this.appinfos); |
||||
} else if (data.code === 1003) { |
||||
this.$router.push({name: 'FirApps'}); |
||||
} else { |
||||
// eslint-disable-next-line no-console |
||||
console.log("Error"); |
||||
} |
||||
}, { |
||||
"methods": "GET", |
||||
"app_id": this.$route.params.id |
||||
}); |
||||
if (this.$store.state.currentapp.master_release) { |
||||
this.set_icon_url() |
||||
} |
||||
}, watch: { |
||||
'$store.state.currentapp.master_release.icon_url': function () { |
||||
this.set_icon_url() |
||||
}, |
||||
'$store.state.currentapp': function () { |
||||
this.appinfos = this.$store.state.currentapp; |
||||
}, |
||||
}, destroyed() { |
||||
this.$store.dispatch('doucurrentapp', {}); |
||||
} |
||||
|
||||
} |
||||
</script> |
||||
|
||||
<style scoped> |
||||
.main { |
||||
margin: 40px auto 100px; |
||||
position: relative; |
||||
padding-bottom: 1px; |
||||
color: #9b9b9b; |
||||
-webkit-font-smoothing: antialiased; |
||||
border-radius: 1%; |
||||
} |
||||
|
||||
.appicon { |
||||
overflow: hidden; |
||||
margin-left: 10px; |
||||
border-radius: 17.544%; |
||||
} |
||||
|
||||
.page-app { |
||||
padding-bottom: 0; |
||||
width: 1166px; |
||||
margin: 10px auto 100px; |
||||
} |
||||
|
||||
.page-app .banner { |
||||
padding-top: 60px; |
||||
padding-bottom: 40px; |
||||
border-bottom: 1px solid rgba(208, 208, 208, .5); |
||||
background-color: #ffffff; |
||||
border-radius: 10px; |
||||
} |
||||
|
||||
.page-app .banner .actions { |
||||
position: absolute; |
||||
right: 0; |
||||
top: 0; |
||||
} |
||||
|
||||
.page-app .banner .actions .download { |
||||
display: block; |
||||
min-width: 150px; |
||||
padding: 10px 20px; |
||||
border-radius: 5px; |
||||
font-size: 14px; |
||||
margin: 0 12px 12px 12px |
||||
} |
||||
|
||||
|
||||
.page-app .banner .actions .download { |
||||
text-align: center; |
||||
text-decoration: none; |
||||
color: #3ab2a7; |
||||
border: 1px solid; |
||||
background-color: transparent |
||||
} |
||||
|
||||
|
||||
.page-app .banner .middle-wrapper { |
||||
position: relative |
||||
} |
||||
|
||||
|
||||
.page-app .badges { |
||||
margin-left: 160px; |
||||
font-size: 12px; |
||||
line-height: initial; |
||||
position: relative; |
||||
margin-top: -100px; |
||||
} |
||||
|
||||
.page-app .badges > span { |
||||
position: relative; |
||||
display: inline-block; |
||||
margin-right: 8px; |
||||
padding: 4px 8px; |
||||
border: 1px solid; |
||||
border-radius: 5px |
||||
} |
||||
|
||||
|
||||
.page-app .badges .short { |
||||
color: #6f6ef8 |
||||
} |
||||
|
||||
.page-app .badges .short:hover { |
||||
cursor: pointer; |
||||
} |
||||
|
||||
.page-app .badges b { |
||||
display: inline-block; |
||||
padding-left: 12px; |
||||
height: 100%; |
||||
font-weight: 400 |
||||
} |
||||
|
||||
.page-app .badges b:before { |
||||
position: absolute; |
||||
top: 0; |
||||
width: 0; |
||||
height: 100%; |
||||
border-left: 1px solid; |
||||
content: ' '; |
||||
margin-left: -6px |
||||
} |
||||
|
||||
.page-app .tabs-container { |
||||
margin-top: 40px; |
||||
margin-left: 160px |
||||
} |
||||
|
||||
.page-app .tabs-container .el-row { |
||||
margin: 10px auto; |
||||
} |
||||
|
||||
.page-app .tabs-container .el-row .el-col { |
||||
margin-right: 30px; |
||||
border-left: 1px solid; |
||||
} |
||||
|
||||
.page-app .tabs-container .el-row .el-col a { |
||||
display: block; |
||||
padding-left: 15px; |
||||
color: #599b1a; |
||||
text-decoration: none; |
||||
-webkit-transition: all .5s; |
||||
transition: all .5s |
||||
} |
||||
|
||||
.page-app .tabs-container .el-row .el-col a > i { |
||||
display: block; |
||||
margin-bottom: 14px; |
||||
height: 22px; |
||||
font-size: 22px |
||||
} |
||||
|
||||
.page-app .tabs-container .el-row .el-col a.active { |
||||
color: #4a4a4a |
||||
} |
||||
|
||||
.page-app .tabs-container .el-row .el-col:nth-child(6) { |
||||
display: none |
||||
} |
||||
|
||||
.page-app .has-devices .tabs-container .el-row .el-col:nth-child(6) { |
||||
display: inline-block |
||||
} |
||||
.main { |
||||
margin: 40px auto 100px; |
||||
position: relative; |
||||
padding-bottom: 1px; |
||||
color: #9b9b9b; |
||||
-webkit-font-smoothing: antialiased; |
||||
border-radius: 1%; |
||||
} |
||||
|
||||
.appicon { |
||||
overflow: hidden; |
||||
margin-left: 10px; |
||||
border-radius: 17.544%; |
||||
} |
||||
|
||||
.page-app { |
||||
padding-bottom: 0; |
||||
width: 1166px; |
||||
margin: 10px auto 100px; |
||||
} |
||||
|
||||
.page-app .banner { |
||||
padding-top: 60px; |
||||
padding-bottom: 40px; |
||||
border-bottom: 1px solid rgba(208, 208, 208, .5); |
||||
background-color: #ffffff; |
||||
border-radius: 10px; |
||||
} |
||||
|
||||
.page-app .banner .actions { |
||||
position: absolute; |
||||
right: 0; |
||||
top: 0; |
||||
} |
||||
|
||||
.page-app .banner .actions .download { |
||||
display: block; |
||||
min-width: 150px; |
||||
padding: 10px 20px; |
||||
border-radius: 5px; |
||||
font-size: 14px; |
||||
margin: 0 12px 12px 12px |
||||
} |
||||
|
||||
|
||||
.page-app .banner .actions .download { |
||||
text-align: center; |
||||
text-decoration: none; |
||||
color: #3ab2a7; |
||||
border: 1px solid; |
||||
background-color: transparent |
||||
} |
||||
|
||||
|
||||
.page-app .banner .middle-wrapper { |
||||
position: relative |
||||
} |
||||
|
||||
|
||||
.page-app .badges { |
||||
margin-left: 160px; |
||||
font-size: 12px; |
||||
line-height: initial; |
||||
position: relative; |
||||
margin-top: -100px; |
||||
} |
||||
|
||||
.page-app .badges > span { |
||||
position: relative; |
||||
display: inline-block; |
||||
margin-right: 8px; |
||||
padding: 4px 8px; |
||||
border: 1px solid; |
||||
border-radius: 5px |
||||
} |
||||
|
||||
|
||||
.page-app .badges .short { |
||||
color: #6f6ef8 |
||||
} |
||||
|
||||
.page-app .badges .short:hover { |
||||
cursor: pointer; |
||||
} |
||||
|
||||
.page-app .badges b { |
||||
display: inline-block; |
||||
padding-left: 12px; |
||||
height: 100%; |
||||
font-weight: 400 |
||||
} |
||||
|
||||
.page-app .badges b:before { |
||||
position: absolute; |
||||
top: 0; |
||||
width: 0; |
||||
height: 100%; |
||||
border-left: 1px solid; |
||||
content: ' '; |
||||
margin-left: -6px |
||||
} |
||||
|
||||
.page-app .tabs-container { |
||||
margin-top: 40px; |
||||
margin-left: 160px |
||||
} |
||||
|
||||
.page-app .tabs-container .el-row { |
||||
margin: 10px auto; |
||||
} |
||||
|
||||
.page-app .tabs-container .el-row .el-col { |
||||
margin-right: 30px; |
||||
border-left: 1px solid; |
||||
} |
||||
|
||||
.page-app .tabs-container .el-row .el-col a { |
||||
display: block; |
||||
padding-left: 15px; |
||||
color: #599b1a; |
||||
text-decoration: none; |
||||
-webkit-transition: all .5s; |
||||
transition: all .5s |
||||
} |
||||
|
||||
.page-app .tabs-container .el-row .el-col a > i { |
||||
display: block; |
||||
margin-bottom: 14px; |
||||
height: 22px; |
||||
font-size: 22px |
||||
} |
||||
|
||||
.page-app .tabs-container .el-row .el-col a.active { |
||||
color: #4a4a4a |
||||
} |
||||
|
||||
.page-app .tabs-container .el-row .el-col:nth-child(6) { |
||||
display: none |
||||
} |
||||
|
||||
.page-app .has-devices .tabs-container .el-row .el-col:nth-child(6) { |
||||
display: inline-block |
||||
} |
||||
|
||||
|
||||
</style> |
||||
|
@ -1,293 +1,295 @@ |
||||
<template> |
||||
<div style="margin-top: 20px;width: 100%;margin-left: 8%"> |
||||
<el-form ref="form" label-width="80px"> |
||||
<el-form-item label="应用ID" style="width: 56%"> |
||||
<el-row> |
||||
<el-col :span="19"> |
||||
<el-input v-model="currentapp.app_id" :disabled="true"/> |
||||
</el-col> |
||||
<el-col :span="4"> |
||||
<el-button type="danger" plain @click="delApp" |
||||
style="margin:0 8px;border-radius:4px;cursor:pointer;height: 40px">删除应用 |
||||
</el-button> |
||||
</el-col> |
||||
</el-row> |
||||
<div style="margin-top: 20px;width: 100%;margin-left: 8%"> |
||||
<el-form ref="form" label-width="80px"> |
||||
<el-form-item label="应用ID" style="width: 56%"> |
||||
<el-row> |
||||
<el-col :span="19"> |
||||
<el-input v-model="currentapp.app_id" :disabled="true"/> |
||||
</el-col> |
||||
<el-col :span="4"> |
||||
<el-button plain style="margin:0 8px;border-radius:4px;cursor:pointer;height: 40px" type="danger" |
||||
@click="delApp">删除应用 |
||||
</el-button> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
<el-form-item label="使用空间" style="width: 56%"> |
||||
<el-input v-model="currentapp.storage_used" :disabled="true" :value="currentapp.storage_used"/> |
||||
</el-form-item> |
||||
<el-form-item label="应用名称" style="width: 56%"> |
||||
<el-input v-model="currentapp.name"/> |
||||
</el-form-item> |
||||
|
||||
</el-form-item> |
||||
<el-form-item label="短链接" style="width: 56%"> |
||||
<el-input v-model="currentapp.short" maxlength="16" show-word-limit type="text"> |
||||
<template slot="prepend">{{ currentapp.preview_url }}/</template> |
||||
</el-input> |
||||
</el-form-item> |
||||
|
||||
<el-form-item label="应用名称" style="width: 56%"> |
||||
<el-input v-model="currentapp.name"/> |
||||
</el-form-item> |
||||
<el-form-item label="应用图标" style="width: 56%"> |
||||
<el-upload |
||||
:before-upload="upload_app_icon" |
||||
:show-file-list="false" |
||||
accept=".png , .jpg , .jpeg" |
||||
action="#" |
||||
class="avatar-uploader"> |
||||
<img v-if="currentapp.icon_url" :src="currentapp.icon_url" |
||||
alt="" class="avatar"> |
||||
<i v-else class="el-icon-plus avatar-uploader-icon"/> |
||||
</el-upload> |
||||
</el-form-item> |
||||
<el-form-item label="应用描述" style="width: 66%"> |
||||
<el-input v-model="currentapp.description" :autosize="{ minRows: 8, maxRows: 18}" |
||||
type="textarea"/> |
||||
</el-form-item> |
||||
<el-form-item> |
||||
<el-row> |
||||
<el-col :span="15"> |
||||
<el-button plain size="medium" style="width: 160px;height: 50px;font-size: large;float: right" |
||||
type="primary" |
||||
@click="saveappinfo('save')">保存信息 |
||||
</el-button> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
<el-divider/> |
||||
<el-form-item label="应用截图" style="width: 100%"> |
||||
|
||||
<el-form-item label="短链接" style="width: 56%"> |
||||
<el-input v-model="currentapp.short" maxlength="16" show-word-limit type="text"> |
||||
<template slot="prepend">{{ currentapp.preview_url }}/</template> |
||||
</el-input> |
||||
</el-form-item> |
||||
<div class="appdownload"> |
||||
<el-tooltip v-for="(screen) in currentapp.screenshots" :key="screen.id" content="点击删除该应用截图" |
||||
effect="light" placement="top"> |
||||
<el-image |
||||
:src="screen.url" |
||||
alt="" |
||||
class="screen-img" |
||||
fit="scale-down" @click="delscreen(screen.id)"> |
||||
<div slot="error" class="image-slot" style="text-align: center;margin-top: 80%" |
||||
@click="delscreen(screen.id)"> |
||||
<i class="el-icon-picture-outline"> 加载失败</i> |
||||
</div> |
||||
</el-image> |
||||
</el-tooltip> |
||||
<div v-if="currentapp.screenshots && currentapp.screenshots.length < 5" |
||||
class="screen-img"> |
||||
<el-upload |
||||
:before-upload="upload_app_screen" |
||||
accept=".png , .jpg , .jpeg" |
||||
action="#" |
||||
drag> |
||||
<i class="el-icon-upload"/> |
||||
</el-upload> |
||||
</div> |
||||
|
||||
<el-form-item label="应用图标" style="width: 56%"> |
||||
<el-upload |
||||
class="avatar-uploader" |
||||
action="#" |
||||
:show-file-list="false" |
||||
accept=".png , .jpg , .jpeg" |
||||
:before-upload="upload_app_icon"> |
||||
<img v-if="currentapp.icon_url" :src="currentapp.icon_url" |
||||
class="avatar" alt=""> |
||||
<i v-else class="el-icon-plus avatar-uploader-icon"/> |
||||
</el-upload> |
||||
</el-form-item> |
||||
<el-form-item label="应用描述" style="width: 66%"> |
||||
<el-input type="textarea" v-model="currentapp.description" |
||||
:autosize="{ minRows: 8, maxRows: 18}"/> |
||||
</el-form-item> |
||||
<el-form-item> |
||||
<el-row> |
||||
<el-col :span="15"> |
||||
<el-button type="primary" plain @click="saveappinfo('save')" size="medium" |
||||
style="width: 160px;height: 50px;font-size: large;float: right">保存信息 |
||||
</el-button> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form-item> |
||||
<el-divider/> |
||||
<el-form-item label="应用截图" style="width: 100%"> |
||||
</div> |
||||
|
||||
<div class="appdownload"> |
||||
<el-tooltip content="点击删除该应用截图" v-for="(screen) in currentapp.screenshots" :key="screen.id" |
||||
placement="top" effect="light"> |
||||
<el-image |
||||
class="screen-img" |
||||
fit="scale-down" |
||||
@click="delscreen(screen.id)" |
||||
:src="screen.url" alt=""> |
||||
<div slot="error" class="image-slot" @click="delscreen(screen.id)" |
||||
style="text-align: center;margin-top: 80%"> |
||||
<i class="el-icon-picture-outline"> 加载失败</i> |
||||
</div> |
||||
</el-image> |
||||
</el-tooltip> |
||||
<div class="screen-img" |
||||
v-if="currentapp.screenshots && currentapp.screenshots.length < 5"> |
||||
<el-upload |
||||
drag |
||||
action="#" |
||||
accept=".png , .jpg , .jpeg" |
||||
:before-upload="upload_app_screen"> |
||||
<i class="el-icon-upload"/> |
||||
</el-upload> |
||||
</div> |
||||
</el-form-item> |
||||
</el-form> |
||||
|
||||
</div> |
||||
|
||||
</el-form-item> |
||||
</el-form> |
||||
|
||||
</div> |
||||
</div> |
||||
|
||||
|
||||
</template> |
||||
|
||||
<script> |
||||
import {apputils, getapppicurl, releaseapputils} from "@/restful" |
||||
import {AvatarUploadUtils} from "@/utils"; |
||||
|
||||
export default { |
||||
name: "FirAppInfosbaseinfo", |
||||
data() { |
||||
return { |
||||
currentapp: {}, |
||||
imageUrl: "", |
||||
uploadconf: {}, |
||||
uploadprocess: 0, |
||||
dialogImageUrl: '', |
||||
dialogVisible: false, |
||||
appinfos: {}, |
||||
} |
||||
}, |
||||
methods: { |
||||
// eslint-disable-next-line no-unused-vars |
||||
delscreen(screen_id) { |
||||
this.$confirm('确定要删除该应用截图?', '警告', { |
||||
confirmButtonText: '确定', |
||||
cancelButtonText: '取消', |
||||
type: 'warning' |
||||
}).then(() => { |
||||
releaseapputils(data => { |
||||
if (data.code === 1000) { |
||||
this.$message.success('删除成功'); |
||||
this.getappinfo(); |
||||
} else if (data.code === 1003) { |
||||
this.$router.push({name: 'FirApps'}); |
||||
} |
||||
}, { |
||||
"methods": "DELETE", |
||||
"app_id": this.$route.params.id, |
||||
"release_id": "screen", |
||||
"data": {'screen_id': screen_id} |
||||
}) |
||||
import {apputils, getapppicurl, releaseapputils} from "@/restful" |
||||
import {AvatarUploadUtils} from "@/utils"; |
||||
|
||||
}).catch(() => { |
||||
this.$message({ |
||||
type: 'info', |
||||
message: '已取消操作' |
||||
}); |
||||
}); |
||||
}, |
||||
export default { |
||||
name: "FirAppInfosbaseinfo", |
||||
data() { |
||||
return { |
||||
currentapp: {}, |
||||
imageUrl: "", |
||||
uploadconf: {}, |
||||
uploadprocess: 0, |
||||
dialogImageUrl: '', |
||||
dialogVisible: false, |
||||
appinfos: {}, |
||||
} |
||||
}, |
||||
methods: { |
||||
// eslint-disable-next-line no-unused-vars |
||||
delscreen(screen_id) { |
||||
this.$confirm('确定要删除该应用截图?', '警告', { |
||||
confirmButtonText: '确定', |
||||
cancelButtonText: '取消', |
||||
type: 'warning' |
||||
}).then(() => { |
||||
releaseapputils(data => { |
||||
if (data.code === 1000) { |
||||
this.$message.success('删除成功'); |
||||
this.getappinfo(); |
||||
} else if (data.code === 1003) { |
||||
this.$router.push({name: 'FirApps'}); |
||||
} |
||||
}, { |
||||
"methods": "DELETE", |
||||
"app_id": this.$route.params.id, |
||||
"release_id": "screen", |
||||
"data": {'screen_id': screen_id} |
||||
}) |
||||
|
||||
delApp() { |
||||
//发送删除APP的操作 |
||||
this.$confirm('确认删除 ' + this.currentapp.name + ' ?') |
||||
// eslint-disable-next-line no-unused-vars |
||||
.then(res => { |
||||
const loadingobj = this.$loading({ |
||||
lock: true, |
||||
text: '操作中,请耐心等待', |
||||
spinner: 'el-icon-loading', |
||||
// background: 'rgba(0, 0, 0, 0.7)' |
||||
}); |
||||
apputils(data => { |
||||
loadingobj.close(); |
||||
if (data.code === 1000) { |
||||
this.$message({ |
||||
message: '删除成功', |
||||
type: 'success' |
||||
}); |
||||
this.$router.push({name: 'FirApps'}); |
||||
} else { |
||||
this.$message({ |
||||
message: '删除失败,请联系管理员', |
||||
type: 'error' |
||||
}); |
||||
} |
||||
}, { |
||||
"methods": "DELETE", |
||||
"app_id": this.currentapp.app_id |
||||
}); |
||||
}).catch(() => { |
||||
this.$message({ |
||||
type: 'info', |
||||
message: '已取消操作' |
||||
}); |
||||
}); |
||||
}, |
||||
|
||||
}) |
||||
.catch(err => { |
||||
this.$message.error(err) |
||||
}); |
||||
}, |
||||
getappinfo() { |
||||
apputils(data => { |
||||
if (data.code === 1000) { |
||||
this.appinfos = data.data; |
||||
this.master_release = data.data.master_release; |
||||
this.appinfos["icon_url"] = this.master_release.icon_url; |
||||
this.$store.dispatch('doucurrentapp', this.appinfos); |
||||
} else if (data.code === 1003) { |
||||
this.$router.push({name: 'FirApps'}); |
||||
} else { |
||||
// eslint-disable-next-line no-console |
||||
console.log("Error"); |
||||
} |
||||
}, { |
||||
"methods": "GET", |
||||
"app_id": this.currentapp.app_id |
||||
delApp() { |
||||
//发送删除APP的操作 |
||||
this.$confirm('确认删除 ' + this.currentapp.name + ' ?') |
||||
// eslint-disable-next-line no-unused-vars |
||||
.then(res => { |
||||
const loadingobj = this.$loading({ |
||||
lock: true, |
||||
text: '操作中,请耐心等待', |
||||
spinner: 'el-icon-loading', |
||||
// background: 'rgba(0, 0, 0, 0.7)' |
||||
}); |
||||
apputils(data => { |
||||
loadingobj.close(); |
||||
if (data.code === 1000) { |
||||
this.$message({ |
||||
message: '删除成功', |
||||
type: 'success' |
||||
}); |
||||
}, |
||||
saveappinfo() { |
||||
apputils(data => { |
||||
if (data.code === 1000) { |
||||
this.$message.success('数据更新成功'); |
||||
} else { |
||||
this.$message.error('操作失败,' + data.msg); |
||||
} |
||||
}, { |
||||
"methods": "PUT", |
||||
"app_id": this.currentapp.app_id, |
||||
"data": { |
||||
"description": this.currentapp.description, |
||||
"short": this.currentapp.short, |
||||
"name": this.currentapp.name, |
||||
} |
||||
this.$router.push({name: 'FirApps'}); |
||||
} else { |
||||
this.$message({ |
||||
message: '删除失败,请联系管理员', |
||||
type: 'error' |
||||
}); |
||||
}, |
||||
upload_app_icon(file) { |
||||
return this.beforeAvatarUpload(file, 'app') |
||||
}, |
||||
upload_app_screen(file) { |
||||
return this.beforeAvatarUpload(file, 'screen') |
||||
}, |
||||
beforeAvatarUpload(file, act) { |
||||
return AvatarUploadUtils(this, file, { |
||||
'app_id': this.currentapp.app_id, |
||||
'upload_key': file.name, |
||||
'ftype': act |
||||
// eslint-disable-next-line no-unused-vars |
||||
}, res => { |
||||
this.getappinfo(); |
||||
}); |
||||
} |
||||
}, |
||||
mounted() { |
||||
this.$store.dispatch('doappInfoIndex', [[18, 18], [18, 18]]); |
||||
if (!this.currentapp.app_id) { |
||||
this.currentapp = this.$store.state.currentapp; |
||||
} |
||||
this.uploadconf = { |
||||
"AuthHeaders": {"Authorization": this.$cookies.get("auth_token")} |
||||
}; |
||||
}, |
||||
watch: { |
||||
'$store.state.currentapp': function () { |
||||
this.currentapp = this.$store.state.currentapp; |
||||
} |
||||
}, computed: { |
||||
getuppicurl() { |
||||
return getapppicurl(this.currentapp.app_id) |
||||
} |
||||
} |
||||
}, { |
||||
"methods": "DELETE", |
||||
"app_id": this.currentapp.app_id |
||||
}); |
||||
|
||||
}) |
||||
.catch(err => { |
||||
this.$message.error(err) |
||||
}); |
||||
}, |
||||
getappinfo() { |
||||
apputils(data => { |
||||
if (data.code === 1000) { |
||||
this.appinfos = data.data; |
||||
this.master_release = data.data.master_release; |
||||
this.appinfos["icon_url"] = this.master_release.icon_url; |
||||
this.$store.dispatch('doucurrentapp', this.appinfos); |
||||
} else if (data.code === 1003) { |
||||
this.$router.push({name: 'FirApps'}); |
||||
} else { |
||||
// eslint-disable-next-line no-console |
||||
console.log("Error"); |
||||
} |
||||
}, { |
||||
"methods": "GET", |
||||
"app_id": this.currentapp.app_id |
||||
}); |
||||
}, |
||||
saveappinfo() { |
||||
apputils(data => { |
||||
if (data.code === 1000) { |
||||
this.$message.success('数据更新成功'); |
||||
} else { |
||||
this.$message.error('操作失败,' + data.msg); |
||||
} |
||||
}, { |
||||
"methods": "PUT", |
||||
"app_id": this.currentapp.app_id, |
||||
"data": { |
||||
"description": this.currentapp.description, |
||||
"short": this.currentapp.short, |
||||
"name": this.currentapp.name, |
||||
} |
||||
}); |
||||
}, |
||||
upload_app_icon(file) { |
||||
return this.beforeAvatarUpload(file, 'app') |
||||
}, |
||||
upload_app_screen(file) { |
||||
return this.beforeAvatarUpload(file, 'screen') |
||||
}, |
||||
beforeAvatarUpload(file, act) { |
||||
return AvatarUploadUtils(this, file, { |
||||
'app_id': this.currentapp.app_id, |
||||
'upload_key': file.name, |
||||
'ftype': act |
||||
// eslint-disable-next-line no-unused-vars |
||||
}, res => { |
||||
this.getappinfo(); |
||||
}); |
||||
} |
||||
}, |
||||
mounted() { |
||||
this.$store.dispatch('doappInfoIndex', [[18, 18], [18, 18]]); |
||||
if (!this.currentapp.app_id) { |
||||
this.currentapp = this.$store.state.currentapp; |
||||
} |
||||
this.uploadconf = { |
||||
"AuthHeaders": {"Authorization": this.$cookies.get("auth_token")} |
||||
}; |
||||
}, |
||||
watch: { |
||||
'$store.state.currentapp': function () { |
||||
this.currentapp = this.$store.state.currentapp; |
||||
} |
||||
}, computed: { |
||||
getuppicurl() { |
||||
return getapppicurl(this.currentapp.app_id) |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style scoped> |
||||
.appdownload /deep/ .el-upload-dragger { |
||||
background: #f1f1f1; |
||||
width: 155px; |
||||
height: 288px; |
||||
} |
||||
.appdownload /deep/ .el-upload-dragger { |
||||
background: #f1f1f1; |
||||
width: 155px; |
||||
height: 288px; |
||||
} |
||||
|
||||
.appdownload /deep/ .el-icon-upload { |
||||
margin-top: 80%; |
||||
} |
||||
.appdownload /deep/ .el-icon-upload { |
||||
margin-top: 80%; |
||||
} |
||||
|
||||
.avatar-uploader .el-upload { |
||||
border: 1px dashed #d9d9d9; |
||||
border-radius: 6px; |
||||
cursor: pointer; |
||||
position: relative; |
||||
overflow: hidden; |
||||
.avatar-uploader .el-upload { |
||||
border: 1px dashed #d9d9d9; |
||||
border-radius: 6px; |
||||
cursor: pointer; |
||||
position: relative; |
||||
overflow: hidden; |
||||
|
||||
} |
||||
} |
||||
|
||||
.screen-img { |
||||
width: 155px; |
||||
height: 288px; |
||||
margin-right: 20px; |
||||
background-color: #f1f1f1; |
||||
float: left |
||||
} |
||||
.screen-img { |
||||
width: 155px; |
||||
height: 288px; |
||||
margin-right: 20px; |
||||
background-color: #f1f1f1; |
||||
float: left |
||||
} |
||||
|
||||
.screen-img:hover { |
||||
background-color: #c2dcf1; |
||||
} |
||||
.screen-img:hover { |
||||
background-color: #c2dcf1; |
||||
} |
||||
|
||||
.avatar-uploader-icon { |
||||
font-size: 28px; |
||||
color: #8c939d; |
||||
width: 178px; |
||||
height: 178px; |
||||
line-height: 178px; |
||||
text-align: center; |
||||
} |
||||
.avatar-uploader-icon { |
||||
font-size: 28px; |
||||
color: #8c939d; |
||||
width: 178px; |
||||
height: 178px; |
||||
line-height: 178px; |
||||
text-align: center; |
||||
} |
||||
|
||||
.avatar { |
||||
height: 100px; |
||||
width: 100px; |
||||
border-radius: 10px; |
||||
display: block; |
||||
} |
||||
.avatar { |
||||
height: 100px; |
||||
width: 100px; |
||||
border-radius: 10px; |
||||
display: block; |
||||
} |
||||
</style> |
||||
|
@ -1,370 +1,370 @@ |
||||
<template> |
||||
<div class="apps-app-combo page-tabcontent "> |
||||
<div class="middle-wrapper"> |
||||
<div class="request-wrapper" v-if="has_combo "> |
||||
<p class="lead text-center ng-scope">已经与 <b>{{ has_combo.name }}</b> 合并</p> |
||||
<table> |
||||
<tr> |
||||
<td><span class="type">{{ currentapp.type|getapptype}}</span></td> |
||||
<td/> |
||||
<td><span class="type">{{ has_combo.type|getapptype}}</span></td> |
||||
</tr> |
||||
<tr> |
||||
<td> |
||||
<div class="icon"><img v-if="cmaster_release" :src="cmaster_release.icon_url" |
||||
class="ng-isolate-scope" alt=""> |
||||
</div> |
||||
</td> |
||||
<td><i class="icon-combo"/></td> |
||||
<td> |
||||
<div class="icon"><img v-if="hmaster_release" :src="hmaster_release.icon_url" |
||||
class="ng-isolate-scope" alt=""> |
||||
</div> |
||||
</td> |
||||
</tr> |
||||
<tr> |
||||
<td class="actions" colspan="3"> |
||||
<el-button @click="each_confirm" round>解除合并</el-button> |
||||
</td> |
||||
</tr> |
||||
</table> |
||||
</div> |
||||
<div v-else> |
||||
<div class="icon-container text-center"> |
||||
<img v-if="cmaster_release" :src="cmaster_release.icon_url" height="128" width="128"> |
||||
</div> |
||||
<div class="apps-list"> |
||||
<div class="known-apps"> |
||||
<p class="lead ng-binding"> |
||||
<b>选择已有的应用进行合并</b> |
||||
</p> |
||||
<div class="apps"> |
||||
<el-link v-if="comboapplists.length ===0 " :underline="false" type="danger">暂无可以合并的应用 |
||||
</el-link> |
||||
<div :key="comboapp.app_id" @click="each_add(comboapp.app_id)" class="app ng-scope" |
||||
v-for="comboapp in comboapplists"> |
||||
<div class="icon"> |
||||
<img :src="comboapp.master_release|geticon_url" class="ng-isolate-scope" alt=""> |
||||
</div> |
||||
<p class="ng-binding">{{ comboapp.name }}</p></div> |
||||
</div> |
||||
</div> |
||||
<span class="hr-vertical"/> |
||||
<div class="find-apps"> |
||||
<p class="lead "> |
||||
<b>输入需要合并的应用的短链接或者名字</b> |
||||
</p> |
||||
<div class="form-group"> |
||||
<el-input |
||||
@click="searchapps" |
||||
clearable |
||||
placeholder="输入短链接或者名字" |
||||
prefix-icon="el-icon-search" |
||||
v-model="searchKey" |
||||
/> |
||||
</div> |
||||
</div> |
||||
<div class="apps-app-combo page-tabcontent "> |
||||
<div class="middle-wrapper"> |
||||
<div v-if="has_combo " class="request-wrapper"> |
||||
<p class="lead text-center ng-scope">已经与 <b>{{ has_combo.name }}</b> 合并</p> |
||||
<table> |
||||
<tr> |
||||
<td><span class="type">{{ currentapp.type|getapptype }}</span></td> |
||||
<td/> |
||||
<td><span class="type">{{ has_combo.type|getapptype }}</span></td> |
||||
</tr> |
||||
<tr> |
||||
<td> |
||||
<div class="icon"><img v-if="cmaster_release" :src="cmaster_release.icon_url" |
||||
alt="" class="ng-isolate-scope"> |
||||
</div> |
||||
</td> |
||||
<td><i class="icon-combo"/></td> |
||||
<td> |
||||
<div class="icon"><img v-if="hmaster_release" :src="hmaster_release.icon_url" |
||||
alt="" class="ng-isolate-scope"> |
||||
</div> |
||||
</td> |
||||
</tr> |
||||
<tr> |
||||
<td class="actions" colspan="3"> |
||||
<el-button round @click="each_confirm">解除合并</el-button> |
||||
</td> |
||||
</tr> |
||||
</table> |
||||
</div> |
||||
<div v-else> |
||||
<div class="icon-container text-center"> |
||||
<img v-if="cmaster_release" :src="cmaster_release.icon_url" height="128" width="128"> |
||||
</div> |
||||
<div class="apps-list"> |
||||
<div class="known-apps"> |
||||
<p class="lead ng-binding"> |
||||
<b>选择已有的应用进行合并</b> |
||||
</p> |
||||
<div class="apps"> |
||||
<el-link v-if="comboapplists.length ===0 " :underline="false" type="danger">暂无可以合并的应用 |
||||
</el-link> |
||||
<div v-for="comboapp in comboapplists" :key="comboapp.app_id" class="app ng-scope" |
||||
@click="each_add(comboapp.app_id)"> |
||||
<div class="icon"> |
||||
<img :src="comboapp.master_release|geticon_url" alt="" class="ng-isolate-scope"> |
||||
</div> |
||||
|
||||
|
||||
<p class="ng-binding">{{ comboapp.name }}</p></div> |
||||
</div> |
||||
|
||||
</div> |
||||
<span class="hr-vertical"/> |
||||
<div class="find-apps"> |
||||
<p class="lead "> |
||||
<b>输入需要合并的应用的短链接或者名字</b> |
||||
</p> |
||||
<div class="form-group"> |
||||
<el-input |
||||
v-model="searchKey" |
||||
clearable |
||||
placeholder="输入短链接或者名字" |
||||
prefix-icon="el-icon-search" |
||||
@click="searchapps" |
||||
/> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
|
||||
</div> |
||||
|
||||
</div> |
||||
|
||||
|
||||
</div> |
||||
|
||||
</template> |
||||
|
||||
<script> |
||||
import {apputils, getapps} from "@/restful"; |
||||
|
||||
export default { |
||||
name: "FirAppInfoscombo" |
||||
, data() { |
||||
return { |
||||
searchKey: '', |
||||
currentapp: {}, |
||||
has_combo: {}, |
||||
cmaster_release: {}, |
||||
hmaster_release: {}, |
||||
comboapplists: [], |
||||
orgapplists: [], |
||||
comboapp: {"master_release": ""} |
||||
} |
||||
}, methods: { |
||||
searchapps() { |
||||
let keysearch = this.searchKey.replace(/^\s+|\s+$/g, ""); |
||||
let newapplists = []; |
||||
for (let i = 0; i < this.orgapplists.length; i++) { |
||||
if (this.orgapplists[i].short.search(keysearch) === 0 || this.orgapplists[i].name.search(keysearch) === 0) { |
||||
newapplists.push(this.orgapplists[i]); |
||||
} |
||||
} |
||||
if (keysearch === "") { |
||||
this.comboapplists = this.orgapplists.slice(); |
||||
} else { |
||||
this.comboapplists = newapplists.slice(); |
||||
} |
||||
}, |
||||
each_add(hcombo_id) { |
||||
apputils(data => { |
||||
if (data.code === 1000) { |
||||
this.$message.success('操作成功'); |
||||
this.comboapplists = []; |
||||
apputils(data => { |
||||
let appinfos = data.data; |
||||
appinfos["icon_url"] = appinfos.master_release.icon_url; |
||||
this.$store.dispatch('doucurrentapp', appinfos); |
||||
|
||||
if (data.code === 1000) { |
||||
this.$store.dispatch('doucurrentapp', data.data); |
||||
} else if (data.code === 1003) { |
||||
this.$router.push({name: 'FirApps'}); |
||||
} else { |
||||
// eslint-disable-next-line no-console |
||||
console.log("Error"); |
||||
} |
||||
}, { |
||||
"methods": "GET", |
||||
"app_id": this.currentapp.app_id |
||||
}); |
||||
this.setData(); |
||||
} |
||||
}, { |
||||
"methods": "PUT", |
||||
"app_id": this.currentapp.app_id, |
||||
"data": { |
||||
"has_combo": { |
||||
"hcombo_id": hcombo_id, |
||||
"action": "COMBO", |
||||
} |
||||
} |
||||
}); |
||||
}, |
||||
each_confirm() { |
||||
apputils(data => { |
||||
if (data.code === 1000) { |
||||
this.$message.success('操作成功'); |
||||
|
||||
let currentapp = this.$store.state.currentapp; |
||||
this.has_combo = this.$store.state.currentapp.has_combo; |
||||
this.has_combo = null; |
||||
currentapp.has_combo = null; |
||||
this.hmaster_release = null; |
||||
this.$store.dispatch('doucurrentapp', currentapp); |
||||
this.getappiconFun(); |
||||
|
||||
} |
||||
}, { |
||||
"methods": "PUT", |
||||
"app_id": this.currentapp.app_id, |
||||
"data": { |
||||
"has_combo": { |
||||
"hcombo_id": this.has_combo.app_id, |
||||
"action": "UNCOMBO", |
||||
} |
||||
} |
||||
}); |
||||
}, |
||||
setData() { |
||||
this.currentapp = this.$store.state.currentapp; |
||||
this.cmaster_release = this.$store.state.currentapp.master_release; |
||||
if (this.$store.state.currentapp.has_combo) { |
||||
this.has_combo = this.$store.state.currentapp.has_combo; |
||||
this.hmaster_release = this.$store.state.currentapp.has_combo.master_release; |
||||
} else { |
||||
this.has_combo = null; |
||||
this.hmaster_release = null; |
||||
this.getappiconFun(); |
||||
} |
||||
}, |
||||
getappiconFun() { |
||||
let type = "android"; |
||||
if (this.currentapp.type === 0) { |
||||
type = "ios" |
||||
} |
||||
getapps(data => { |
||||
if (data.code === 1000) { |
||||
this.comboapplists = data.data; |
||||
this.orgapplists = this.comboapplists.slice(); //深拷贝 |
||||
|
||||
} else { |
||||
this.$router.push({name: 'FirLogin'}); |
||||
} |
||||
}, {"type": type, "page": 1, "size": 999, "act": 'combo'}); |
||||
import {apputils, getapps} from "@/restful"; |
||||
|
||||
export default { |
||||
name: "FirAppInfoscombo" |
||||
, data() { |
||||
return { |
||||
searchKey: '', |
||||
currentapp: {}, |
||||
has_combo: {}, |
||||
cmaster_release: {}, |
||||
hmaster_release: {}, |
||||
comboapplists: [], |
||||
orgapplists: [], |
||||
comboapp: {"master_release": ""} |
||||
} |
||||
}, methods: { |
||||
searchapps() { |
||||
let keysearch = this.searchKey.replace(/^\s+|\s+$/g, ""); |
||||
let newapplists = []; |
||||
for (let i = 0; i < this.orgapplists.length; i++) { |
||||
if (this.orgapplists[i].short.search(keysearch) === 0 || this.orgapplists[i].name.search(keysearch) === 0) { |
||||
newapplists.push(this.orgapplists[i]); |
||||
} |
||||
} |
||||
if (keysearch === "") { |
||||
this.comboapplists = this.orgapplists.slice(); |
||||
} else { |
||||
this.comboapplists = newapplists.slice(); |
||||
} |
||||
}, |
||||
each_add(hcombo_id) { |
||||
apputils(data => { |
||||
if (data.code === 1000) { |
||||
this.$message.success('操作成功'); |
||||
this.comboapplists = []; |
||||
apputils(data => { |
||||
let appinfos = data.data; |
||||
appinfos["icon_url"] = appinfos.master_release.icon_url; |
||||
this.$store.dispatch('doucurrentapp', appinfos); |
||||
|
||||
if (data.code === 1000) { |
||||
this.$store.dispatch('doucurrentapp', data.data); |
||||
} else if (data.code === 1003) { |
||||
this.$router.push({name: 'FirApps'}); |
||||
} else { |
||||
// eslint-disable-next-line no-console |
||||
console.log("Error"); |
||||
} |
||||
}, filters: { |
||||
geticon_url(app) { |
||||
if (app) { |
||||
return app.icon_url |
||||
} |
||||
return "" |
||||
}, |
||||
getapptype: function (type) { |
||||
let ftype = ''; |
||||
if (type === 0) { |
||||
ftype = 'Android' |
||||
} else { |
||||
ftype = 'iOS' |
||||
} |
||||
return ftype |
||||
}, |
||||
}, |
||||
mounted() { |
||||
this.$store.dispatch('doappInfoIndex', [[44, 44], [44, 44]]); |
||||
this.setData(); |
||||
}, |
||||
watch: { |
||||
'$store.state.currentapp': function () { |
||||
this.setData(); |
||||
}, |
||||
// eslint-disable-next-line no-unused-vars |
||||
searchKey: function (val, oldVal) { |
||||
this.searchapps() |
||||
}, |
||||
}, { |
||||
"methods": "GET", |
||||
"app_id": this.currentapp.app_id |
||||
}); |
||||
this.setData(); |
||||
} |
||||
}, { |
||||
"methods": "PUT", |
||||
"app_id": this.currentapp.app_id, |
||||
"data": { |
||||
"has_combo": { |
||||
"hcombo_id": hcombo_id, |
||||
"action": "COMBO", |
||||
} |
||||
} |
||||
}); |
||||
}, |
||||
each_confirm() { |
||||
apputils(data => { |
||||
if (data.code === 1000) { |
||||
this.$message.success('操作成功'); |
||||
|
||||
let currentapp = this.$store.state.currentapp; |
||||
this.has_combo = this.$store.state.currentapp.has_combo; |
||||
this.has_combo = null; |
||||
currentapp.has_combo = null; |
||||
this.hmaster_release = null; |
||||
this.$store.dispatch('doucurrentapp', currentapp); |
||||
this.getappiconFun(); |
||||
|
||||
} |
||||
}, { |
||||
"methods": "PUT", |
||||
"app_id": this.currentapp.app_id, |
||||
"data": { |
||||
"has_combo": { |
||||
"hcombo_id": this.has_combo.app_id, |
||||
"action": "UNCOMBO", |
||||
} |
||||
} |
||||
}); |
||||
}, |
||||
setData() { |
||||
this.currentapp = this.$store.state.currentapp; |
||||
this.cmaster_release = this.$store.state.currentapp.master_release; |
||||
if (this.$store.state.currentapp.has_combo) { |
||||
this.has_combo = this.$store.state.currentapp.has_combo; |
||||
this.hmaster_release = this.$store.state.currentapp.has_combo.master_release; |
||||
} else { |
||||
this.has_combo = null; |
||||
this.hmaster_release = null; |
||||
this.getappiconFun(); |
||||
} |
||||
}, |
||||
getappiconFun() { |
||||
let type = "android"; |
||||
if (this.currentapp.type === 0) { |
||||
type = "ios" |
||||
} |
||||
getapps(data => { |
||||
if (data.code === 1000) { |
||||
this.comboapplists = data.data; |
||||
this.orgapplists = this.comboapplists.slice(); //深拷贝 |
||||
|
||||
} else { |
||||
this.$router.push({name: 'FirLogin'}); |
||||
} |
||||
}, {"type": type, "page": 1, "size": 999, "act": 'combo'}); |
||||
} |
||||
}, filters: { |
||||
geticon_url(app) { |
||||
if (app) { |
||||
return app.icon_url |
||||
} |
||||
return "" |
||||
}, |
||||
getapptype: function (type) { |
||||
let ftype = ''; |
||||
if (type === 0) { |
||||
ftype = 'Android' |
||||
} else { |
||||
ftype = 'iOS' |
||||
} |
||||
return ftype |
||||
}, |
||||
}, |
||||
mounted() { |
||||
this.$store.dispatch('doappInfoIndex', [[44, 44], [44, 44]]); |
||||
this.setData(); |
||||
}, |
||||
watch: { |
||||
'$store.state.currentapp': function () { |
||||
this.setData(); |
||||
}, |
||||
// eslint-disable-next-line no-unused-vars |
||||
searchKey: function (val, oldVal) { |
||||
this.searchapps() |
||||
}, |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style scoped> |
||||
|
||||
|
||||
.text-center { |
||||
text-align: center |
||||
} |
||||
|
||||
.middle-wrapper { |
||||
margin: 0 auto; |
||||
width: 1100px |
||||
} |
||||
|
||||
.apps-app-combo { |
||||
position: relative; |
||||
padding-top: 45px |
||||
} |
||||
|
||||
.apps-app-combo .icon-container { |
||||
margin-bottom: 60px |
||||
} |
||||
|
||||
.apps-app-combo .icon-container img { |
||||
border-radius: 17.544% |
||||
} |
||||
|
||||
.apps-app-combo .apps-list { |
||||
position: relative; |
||||
overflow: hidden |
||||
} |
||||
|
||||
.apps-app-combo .lead { |
||||
margin-bottom: 30px; |
||||
font-size: 16px |
||||
} |
||||
|
||||
.apps-app-combo .lead b { |
||||
max-width: 300px; |
||||
display: inline-block; |
||||
white-space: nowrap; |
||||
overflow: hidden; |
||||
text-overflow: ellipsis; |
||||
vertical-align: top |
||||
} |
||||
|
||||
.known-apps { |
||||
text-align: center; |
||||
float: left; |
||||
width: 45%; |
||||
margin: 10px 30px; |
||||
} |
||||
|
||||
.apps-app-combo .known-apps .icon img { |
||||
width: 80px; |
||||
height: 80px; |
||||
border-radius: 22.7% |
||||
} |
||||
|
||||
.apps-app-combo .known-apps .apps .app { |
||||
display: inline-block; |
||||
margin: 0 0 20px 28px; |
||||
text-align: center; |
||||
cursor: pointer; |
||||
vertical-align: top; |
||||
|
||||
} |
||||
|
||||
.apps-app-combo .known-apps .apps .app > p { |
||||
margin-top: 8px; |
||||
font-size: 12px; |
||||
text-align: center; |
||||
display: inline-block; |
||||
max-width: 100px; |
||||
overflow: hidden; |
||||
text-overflow: ellipsis; |
||||
white-space: nowrap; |
||||
word-wrap: normal |
||||
} |
||||
|
||||
.apps-app-combo .find-apps { |
||||
/*padding-left: 50px;*/ |
||||
text-align: center; |
||||
margin: 10px 30px; |
||||
float: right; |
||||
width: 40%; |
||||
} |
||||
|
||||
.apps-app-combo .find-apps .lead { |
||||
text-align: left; |
||||
} |
||||
|
||||
.apps-app-combo .find-apps .form-group { |
||||
position: relative; |
||||
margin-bottom: 36px; |
||||
width: 260px; |
||||
} |
||||
|
||||
.apps-app-combo .hr-vertical { |
||||
position: absolute; |
||||
z-index: 12; |
||||
width: 1px; |
||||
height: 100%; |
||||
background-color: #d5f9f9 |
||||
} |
||||
|
||||
.apps-app-combo .request-wrapper .lead { |
||||
margin-bottom: 80px; |
||||
font-size: 18px |
||||
} |
||||
|
||||
.apps-app-combo .request-wrapper table { |
||||
margin: 0 auto; |
||||
width: 400px |
||||
} |
||||
|
||||
.apps-app-combo .request-wrapper table tr:first-child td span { |
||||
display: inline-block; |
||||
margin-bottom: 12px; |
||||
font-size: 16px |
||||
} |
||||
|
||||
.apps-app-combo .request-wrapper table td { |
||||
padding: 0 15px; |
||||
text-align: center |
||||
} |
||||
|
||||
.apps-app-combo .request-wrapper table td img { |
||||
width: 120px; |
||||
height: 120px; |
||||
border-radius: 17.54% |
||||
} |
||||
|
||||
.apps-app-combo .request-wrapper table .actions { |
||||
padding-top: 40px |
||||
} |
||||
|
||||
.apps-app-combo .request-wrapper table i.icon-combo { |
||||
font-size: 30px |
||||
} |
||||
.text-center { |
||||
text-align: center |
||||
} |
||||
|
||||
.middle-wrapper { |
||||
margin: 0 auto; |
||||
width: 1100px |
||||
} |
||||
|
||||
.apps-app-combo { |
||||
position: relative; |
||||
padding-top: 45px |
||||
} |
||||
|
||||
.apps-app-combo .icon-container { |
||||
margin-bottom: 60px |
||||
} |
||||
|
||||
.apps-app-combo .icon-container img { |
||||
border-radius: 17.544% |
||||
} |
||||
|
||||
.apps-app-combo .apps-list { |
||||
position: relative; |
||||
overflow: hidden |
||||
} |
||||
|
||||
.apps-app-combo .lead { |
||||
margin-bottom: 30px; |
||||
font-size: 16px |
||||
} |
||||
|
||||
.apps-app-combo .lead b { |
||||
max-width: 300px; |
||||
display: inline-block; |
||||
white-space: nowrap; |
||||
overflow: hidden; |
||||
text-overflow: ellipsis; |
||||
vertical-align: top |
||||
} |
||||
|
||||
.known-apps { |
||||
text-align: center; |
||||
float: left; |
||||
width: 45%; |
||||
margin: 10px 30px; |
||||
} |
||||
|
||||
.apps-app-combo .known-apps .icon img { |
||||
width: 80px; |
||||
height: 80px; |
||||
border-radius: 22.7% |
||||
} |
||||
|
||||
.apps-app-combo .known-apps .apps .app { |
||||
display: inline-block; |
||||
margin: 0 0 20px 28px; |
||||
text-align: center; |
||||
cursor: pointer; |
||||
vertical-align: top; |
||||
|
||||
} |
||||
|
||||
.apps-app-combo .known-apps .apps .app > p { |
||||
margin-top: 8px; |
||||
font-size: 12px; |
||||
text-align: center; |
||||
display: inline-block; |
||||
max-width: 100px; |
||||
overflow: hidden; |
||||
text-overflow: ellipsis; |
||||
white-space: nowrap; |
||||
word-wrap: normal |
||||
} |
||||
|
||||
.apps-app-combo .find-apps { |
||||
/*padding-left: 50px;*/ |
||||
text-align: center; |
||||
margin: 10px 30px; |
||||
float: right; |
||||
width: 40%; |
||||
} |
||||
|
||||
.apps-app-combo .find-apps .lead { |
||||
text-align: left; |
||||
} |
||||
|
||||
.apps-app-combo .find-apps .form-group { |
||||
position: relative; |
||||
margin-bottom: 36px; |
||||
width: 260px; |
||||
} |
||||
|
||||
.apps-app-combo .hr-vertical { |
||||
position: absolute; |
||||
z-index: 12; |
||||
width: 1px; |
||||
height: 100%; |
||||
background-color: #d5f9f9 |
||||
} |
||||
|
||||
.apps-app-combo .request-wrapper .lead { |
||||
margin-bottom: 80px; |
||||
font-size: 18px |
||||
} |
||||
|
||||
.apps-app-combo .request-wrapper table { |
||||
margin: 0 auto; |
||||
width: 400px |
||||
} |
||||
|
||||
.apps-app-combo .request-wrapper table tr:first-child td span { |
||||
display: inline-block; |
||||
margin-bottom: 12px; |
||||
font-size: 16px |
||||
} |
||||
|
||||
.apps-app-combo .request-wrapper table td { |
||||
padding: 0 15px; |
||||
text-align: center |
||||
} |
||||
|
||||
.apps-app-combo .request-wrapper table td img { |
||||
width: 120px; |
||||
height: 120px; |
||||
border-radius: 17.54% |
||||
} |
||||
|
||||
.apps-app-combo .request-wrapper table .actions { |
||||
padding-top: 40px |
||||
} |
||||
|
||||
.apps-app-combo .request-wrapper table i.icon-combo { |
||||
font-size: 30px |
||||
} |
||||
|
||||
|
||||
</style> |
||||
|
@ -1,486 +1,472 @@ |
||||
<template> |
||||
<el-timeline> |
||||
<el-timeline-item v-for="(app) in release_apps" :key="app.release_id" |
||||
:timestamp="app.created_time|formatdatatimeline" |
||||
:color="app.master_color" |
||||
placement="top"> |
||||
<el-card> |
||||
<div class="directive-view-release"> |
||||
|
||||
<i class="el-icon-cloudy" v-if="! app.is_master"/> |
||||
<i class="el-icon-cloudy" style="background-color: rgb(139,195,248)" v-else/> |
||||
|
||||
<b class="ng-binding">{{app.app_version}} (Build {{app.build_version}})</b> |
||||
<div class="release-metainfo ng-hide" |
||||
v-if="app.release_type === 0"> |
||||
<small> |
||||
<i class="icon-calendar"/> |
||||
<span class="el-icon-date"> {{app.created_time|formattimeline}}</span> |
||||
</small> |
||||
</div> |
||||
|
||||
<div class="release-metainfo" v-else> |
||||
<small> |
||||
<i class="icon-calendar"/> |
||||
<span class="el-icon-date"> {{app.created_time|formattimeline}}</span> |
||||
</small> · |
||||
|
||||
<small>{{app.release_type|getiOStype}}</small> |
||||
<small v-if="app.distribution_name" style="margin-left: 5px"> · {{app.distribution_name}}</small> |
||||
</div> |
||||
|
||||
<p>{{app.changelog}}</p> |
||||
<label> |
||||
<el-timeline> |
||||
<el-timeline-item v-for="(app) in release_apps" :key="app.release_id" |
||||
:color="app.master_color" |
||||
:timestamp="app.created_time|formatdatatimeline" |
||||
placement="top"> |
||||
<el-card :body-style="{border: app.is_master ? '#2abb9d 1px solid' : ''}"> |
||||
<div class="directive-view-release"> |
||||
|
||||
<i v-if="! app.is_master" class="el-icon-cloudy"/> |
||||
<i v-else class="el-icon-cloudy" style="background-color: rgb(139,195,248)"/> |
||||
|
||||
<b class="ng-binding">{{ app.app_version }} (Build {{ app.build_version }})</b> |
||||
<div v-if="app.release_type === 0" |
||||
class="release-metainfo ng-hide"> |
||||
<small> |
||||
<i class="icon-calendar"/> |
||||
<span class="el-icon-date"> {{ app.created_time|formattimeline }}</span> |
||||
</small> |
||||
</div> |
||||
|
||||
<div v-else class="release-metainfo"> |
||||
<small> |
||||
<i class="icon-calendar"/> |
||||
<span class="el-icon-date"> {{ app.created_time|formattimeline }}</span> |
||||
</small> · |
||||
|
||||
<small>{{ app.release_type|getiOStype }}</small> |
||||
<small v-if="app.distribution_name" |
||||
style="margin-left: 5px"> · {{ app.distribution_name }}</small> |
||||
</div> |
||||
|
||||
<p>{{ app.changelog }}</p> |
||||
<label> |
||||
<textarea v-if="app.editing.changelog" |
||||
v-model="app.changelog" |
||||
placeholder="更新日志"> |
||||
</textarea> |
||||
</label> |
||||
<div class="release-actions editing " v-if="app.editing.changelog"> |
||||
<button class="btn-cancel" @click="endEdit(app,'changelog')"><span |
||||
>取消</span></button> |
||||
<button class="btn-save" @click="updateChangelog(app,'changelog')"><span |
||||
>保存</span></button> |
||||
</div> |
||||
<el-input v-if="app.editing.binary_url" |
||||
v-model="app.binary_url" |
||||
placeholder="下载地址,默认本服务器,填写第三方可以 自动跳转到第三方平台" clearable> |
||||
</el-input> |
||||
<div class="release-actions editing " v-if="app.editing.binary_url" style="margin-top: 10px"> |
||||
|
||||
<button class="btn-cancel" @click="endEdit(app,'binary_url')"><span |
||||
>取消</span></button> |
||||
<button class="btn-save" @click="updateChangelog(app,'binary_url')"><span |
||||
>保存</span></button> |
||||
</div> |
||||
<div class="release-actions" v-show="!app.editing.changelog && !app.editing.binary_url "> |
||||
<el-tooltip class="tooltip-top" content="编辑更新日志" placement="top"> |
||||
<el-button @click="startEdit(app,'changelog')" |
||||
tooltip="编辑更新日志" |
||||
class="tooltip-top "> |
||||
<i class="el-icon-edit"/> |
||||
</el-button> |
||||
</el-tooltip> |
||||
<el-tooltip class="tooltip-top" content="下载原文件" placement="top"> |
||||
<el-button class="tooltip-top" tooltip="下载原文件" |
||||
@click="downloadPackage(app)"> |
||||
<i class="el-icon-download"/> |
||||
<span>{{app.binary_size}}</span> |
||||
</el-button> |
||||
</el-tooltip> |
||||
|
||||
<el-tooltip class="tooltip-top" :content="app.binary_url|downcontent" placement="top"> |
||||
|
||||
<el-button class="tooltip-top" tooltip="修改下载地址" |
||||
@click="startEdit(app,'binary_url')"><i class="el-icon-link"/> <span>下载地址</span> |
||||
</el-button> |
||||
|
||||
</el-tooltip> |
||||
|
||||
<el-button class="tooltip-top" @click="previewRelase(app)"><i class="el-icon-view"/> <span |
||||
class="ng-binding">预览</span> |
||||
</el-button> |
||||
|
||||
<el-button v-if="! app.is_master" class="tooltip-top" @click="make_master_release(app)"> |
||||
<i class="el-icon-view"/> |
||||
<span class="ng-binding ng-scope">标记上线</span> |
||||
</el-button> |
||||
|
||||
<el-button v-if="(! app.is_master )|| (app.is_master && release_apps.length === 1)" |
||||
class="tooltip-top" @click="del_release_app(app)"> |
||||
<i class="el-icon-delete"/> |
||||
<span class="ng-binding ng-scope">删除</span> |
||||
</el-button> |
||||
|
||||
</div> |
||||
</div> |
||||
</el-card> |
||||
</el-timeline-item> |
||||
<el-button v-if="has_next" class="time-line-more" @click="getapptimelineFun('more')">显示更多版本</el-button> |
||||
</el-timeline> |
||||
</label> |
||||
<div v-if="app.editing.changelog" class="release-actions editing "> |
||||
<button class="btn-cancel" @click="endEdit(app,'changelog')"><span |
||||
>取消</span></button> |
||||
<button class="btn-save" @click="updateChangelog(app,'changelog')"><span |
||||
>保存</span></button> |
||||
</div> |
||||
<el-input v-if="app.editing.binary_url" |
||||
v-model="app.binary_url" |
||||
clearable placeholder="下载地址,默认本服务器,填写第三方可以 自动跳转到第三方平台"> |
||||
</el-input> |
||||
<div v-if="app.editing.binary_url" class="release-actions editing " style="margin-top: 10px"> |
||||
|
||||
<button class="btn-cancel" @click="endEdit(app,'binary_url')"><span |
||||
>取消</span></button> |
||||
<button class="btn-save" @click="updateChangelog(app,'binary_url')"><span |
||||
>保存</span></button> |
||||
</div> |
||||
<div v-show="!app.editing.changelog && !app.editing.binary_url " class="release-actions"> |
||||
<el-tooltip class="tooltip-top" content="编辑更新日志" placement="top"> |
||||
<el-button class="tooltip-top " |
||||
tooltip="编辑更新日志" |
||||
@click="startEdit(app,'changelog')"> |
||||
<i class="el-icon-edit"/> |
||||
</el-button> |
||||
</el-tooltip> |
||||
<el-tooltip class="tooltip-top" content="下载原文件" placement="top"> |
||||
<el-button class="tooltip-top" tooltip="下载原文件" |
||||
@click="downloadPackage(app)"> |
||||
<i class="el-icon-download"/> |
||||
<span>{{ app.binary_size }}</span> |
||||
</el-button> |
||||
</el-tooltip> |
||||
|
||||
<el-tooltip :content="app.binary_url|downcontent" class="tooltip-top" placement="top"> |
||||
|
||||
<el-button class="tooltip-top" tooltip="修改下载地址" |
||||
@click="startEdit(app,'binary_url')"><i class="el-icon-link"/> <span>下载地址</span> |
||||
</el-button> |
||||
|
||||
</el-tooltip> |
||||
|
||||
<el-button v-if="!currentapp.issupersign" class="tooltip-top" @click="previewRelease(app)"><i |
||||
class="el-icon-view"/> <span |
||||
class="ng-binding">预览该版本</span> |
||||
</el-button> |
||||
|
||||
<el-button v-if="! app.is_master" class="tooltip-top" @click="make_master_release(app)"> |
||||
<i class="el-icon-view"/> |
||||
<span class="ng-binding ng-scope">标记上线</span> |
||||
</el-button> |
||||
|
||||
<el-button v-if="(! app.is_master )|| (app.is_master && release_apps.length === 1)" |
||||
class="tooltip-top" @click="del_release_app(app)"> |
||||
<i class="el-icon-delete"/> |
||||
<span class="ng-binding ng-scope">删除</span> |
||||
</el-button> |
||||
|
||||
</div> |
||||
</div> |
||||
</el-card> |
||||
</el-timeline-item> |
||||
<el-button v-if="has_next" class="time-line-more" @click="getAppTimelineFun('more')">显示更多版本</el-button> |
||||
</el-timeline> |
||||
</template> |
||||
|
||||
<script> |
||||
import {getdownloadurl, releaseapputils} from "@/restful" |
||||
|
||||
export default { |
||||
name: "FirAppInfostimeline", |
||||
data() { |
||||
return { |
||||
release_apps: [], |
||||
currentapp: {}, |
||||
activity: { |
||||
editing: {'changelog': false, 'binary_url': false} |
||||
}, |
||||
updatas: {}, |
||||
query: {'page': 1, size: 10}, |
||||
has_next: false, |
||||
import {releaseapputils} from "@/restful" |
||||
|
||||
export default { |
||||
name: "FirAppInfostimeline", |
||||
data() { |
||||
return { |
||||
release_apps: [], |
||||
currentapp: {}, |
||||
activity: { |
||||
editing: {'changelog': false, 'binary_url': false} |
||||
}, |
||||
updatas: {}, |
||||
query: {'page': 1, size: 10}, |
||||
has_next: false, |
||||
} |
||||
}, |
||||
methods: { |
||||
set_query_page() { |
||||
if (this.has_next) { |
||||
this.query.page += 1; |
||||
} |
||||
}, |
||||
downloadPackage(app) { |
||||
|
||||
releaseapputils(res => { |
||||
if (res.code === 1000) { |
||||
window.location.href = res.data.download_url; |
||||
} else { |
||||
this.$message.error(res.msg); |
||||
} |
||||
}, |
||||
methods: { |
||||
set_query_page() { |
||||
if (this.has_next) { |
||||
this.query.page += 1; |
||||
} |
||||
}, |
||||
downloadPackage(app) { |
||||
getdownloadurl(res => { |
||||
if (res.code === 1000) { |
||||
window.location.href = res.data.download_url; |
||||
} else { |
||||
this.$message.error(res.msg); |
||||
} |
||||
}, { |
||||
'data': { |
||||
'token': app.download_token, |
||||
'short': this.currentapp.short, |
||||
'release_id': app.release_id, |
||||
"password": this.currentapp.password, |
||||
"isdownload": true, |
||||
}, |
||||
'app_id': this.currentapp.app_id |
||||
}) |
||||
}, |
||||
previewRelase(app) { |
||||
let routeData = this.$router.resolve({ |
||||
name: 'FirDownload', |
||||
params: {short: this.currentapp.short}, |
||||
query: {release_id: app.release_id} |
||||
}); |
||||
let p_url = routeData.href; |
||||
if (this.currentapp.preview_url && this.currentapp.preview_url.length > 6) { |
||||
p_url = this.currentapp.preview_url + p_url |
||||
} |
||||
window.open(p_url, 'target', ''); |
||||
|
||||
}, |
||||
getapptimelineFun(act = '') { |
||||
const loading = this.$loading({ |
||||
lock: true, |
||||
text: '加载中', |
||||
spinner: 'el-icon-loading', |
||||
// background: 'rgba(0, 0, 0, 0.7)' |
||||
}); |
||||
if (act === 'more') { |
||||
this.set_query_page(); |
||||
} else { |
||||
this.release_apps = []; |
||||
this.query = {'page': 1, size: 10}; |
||||
} |
||||
releaseapputils(data => { |
||||
if (data.code === 1000) { |
||||
this.currentapp = data.data.currentapp; |
||||
this.has_next = data.data.has_next; |
||||
this.release_apps = this.release_apps.concat(data.data.release_apps); |
||||
} else if (data.code === 1003) { |
||||
loading.close(); |
||||
this.$router.push({name: 'FirApps'}); |
||||
} |
||||
loading.close(); |
||||
}, { |
||||
"methods": "GET", |
||||
"app_id": this.$route.params.id, |
||||
"release_id": "timeline", |
||||
"data": { |
||||
"page": this.query.page, |
||||
"size": this.query.size |
||||
} |
||||
}) |
||||
}, |
||||
del_release_app(app) { |
||||
//发送删除APP的操作 |
||||
this.$confirm('确认删除 ' + this.currentapp.name + '下 当前 release 版本吗?') |
||||
// eslint-disable-next-line no-unused-vars |
||||
.then(res => { |
||||
let loadingobj = this.$loading({ |
||||
lock: true, |
||||
text: '操作中,请耐心等待', |
||||
spinner: 'el-icon-loading', |
||||
// background: 'rgba(0, 0, 0, 0.7)' |
||||
}); |
||||
releaseapputils(data => { |
||||
loadingobj.close(); |
||||
if (data.code === 1000) { |
||||
this.$message({ |
||||
message: '删除成功', |
||||
type: 'success' |
||||
}); |
||||
this.getapptimelineFun(); |
||||
|
||||
} else { |
||||
this.$message({ |
||||
message: '删除失败,请联系管理员', |
||||
type: 'error' |
||||
}); |
||||
} |
||||
}, { |
||||
"methods": "DELETE", |
||||
"app_id": this.currentapp.app_id, |
||||
"release_id": app.release_id, |
||||
}); |
||||
}); |
||||
|
||||
}, |
||||
updatereleaseappFun(params) { |
||||
releaseapputils(data => { |
||||
if (data.code === 1000) { |
||||
this.$message({ |
||||
message: '更新成功', |
||||
type: 'success' |
||||
}); |
||||
this.release_apps = data.data.release_apps; |
||||
this.currentapp = data.data.currentapp; |
||||
// this.getapptimelineFun(); |
||||
// this.currentapp["icon_url"] = this.currentapp.master_release.icon_url; |
||||
// this.$store.dispatch('doucurrentapp', this.currentapp); |
||||
|
||||
} else { |
||||
this.$message({ |
||||
message: '更新失败,请联系管理员', |
||||
type: 'error' |
||||
}); |
||||
} |
||||
}, params |
||||
); |
||||
}, |
||||
make_master_release(app) { |
||||
this.updatereleaseappFun({ |
||||
"methods": "PUT", |
||||
"app_id": this.currentapp.app_id, |
||||
"release_id": app.release_id, |
||||
"data": { |
||||
"make_master": app.release_id |
||||
} |
||||
}, { |
||||
methods: 'POST', |
||||
app_id: this.currentapp.app_id, |
||||
release_id: app.release_id, |
||||
data: {'token': app.download_token, 'short': this.currentapp.short} |
||||
} |
||||
); |
||||
}, |
||||
previewRelease(app) { |
||||
window.open(this.currentapp.preview_url + '?release_id=' + app.release_id, '_blank', ''); |
||||
}, |
||||
getAppTimelineFun(act = '') { |
||||
const loading = this.$loading({ |
||||
lock: true, |
||||
text: '加载中', |
||||
spinner: 'el-icon-loading', |
||||
// background: 'rgba(0, 0, 0, 0.7)' |
||||
}); |
||||
if (act === 'more') { |
||||
this.set_query_page(); |
||||
} else { |
||||
this.release_apps = []; |
||||
this.query = {'page': 1, size: 10}; |
||||
} |
||||
releaseapputils(data => { |
||||
if (data.code === 1000) { |
||||
this.currentapp = data.data.currentapp; |
||||
this.has_next = data.data.has_next; |
||||
this.release_apps = this.release_apps.concat(data.data.release_apps); |
||||
} else if (data.code === 1003) { |
||||
loading.close(); |
||||
this.$router.push({name: 'FirApps'}); |
||||
} |
||||
loading.close(); |
||||
}, { |
||||
"methods": "GET", |
||||
"app_id": this.$route.params.id, |
||||
"release_id": "timeline", |
||||
"data": { |
||||
"page": this.query.page, |
||||
"size": this.query.size |
||||
} |
||||
}) |
||||
}, |
||||
del_release_app(app) { |
||||
//发送删除APP的操作 |
||||
this.$confirm('确认删除 ' + this.currentapp.name + '下 当前 release 版本吗?') |
||||
// eslint-disable-next-line no-unused-vars |
||||
.then(res => { |
||||
let loadingobj = this.$loading({ |
||||
lock: true, |
||||
text: '操作中,请耐心等待', |
||||
spinner: 'el-icon-loading', |
||||
// background: 'rgba(0, 0, 0, 0.7)' |
||||
}); |
||||
releaseapputils(data => { |
||||
loadingobj.close(); |
||||
if (data.code === 1000) { |
||||
this.$message({ |
||||
message: '删除成功', |
||||
type: 'success' |
||||
}); |
||||
this.getAppTimelineFun(); |
||||
|
||||
}, |
||||
endEdit(app, type) { |
||||
if (type === 'changelog') { |
||||
app.editing.changelog = false; |
||||
|
||||
} else if (type === 'binary_url') { |
||||
app.editing.binary_url = false; |
||||
} |
||||
}, |
||||
updateChangelog(app, type) { |
||||
if (type === 'changelog') { |
||||
this.activity.editing.changelog = false; |
||||
this.updatas = {"changelog": app.changelog} |
||||
} else if (type === 'binary_url') { |
||||
this.activity.editing.binary_url = false; |
||||
this.updatas = {"binary_url": app.binary_url} |
||||
} |
||||
this.updatereleaseappFun({ |
||||
"methods": "PUT", |
||||
"app_id": this.currentapp.app_id, |
||||
"release_id": app.release_id, |
||||
"data": this.updatas |
||||
} else { |
||||
this.$message({ |
||||
message: '删除失败,请联系管理员', |
||||
type: 'error' |
||||
}); |
||||
this.updatas = {} |
||||
}, |
||||
startEdit(app, type) { |
||||
if (type === 'changelog') { |
||||
|
||||
app.editing.changelog = true; |
||||
} else if (type === 'binary_url') { |
||||
app.editing.binary_url = true; |
||||
} |
||||
} |
||||
}, { |
||||
"methods": "DELETE", |
||||
"app_id": this.currentapp.app_id, |
||||
"release_id": app.release_id, |
||||
}); |
||||
}); |
||||
|
||||
}, |
||||
updatereleaseappFun(params) { |
||||
releaseapputils(data => { |
||||
if (data.code === 1000) { |
||||
this.$message({ |
||||
message: '更新成功', |
||||
type: 'success' |
||||
}); |
||||
this.release_apps = data.data.release_apps; |
||||
this.currentapp = data.data.currentapp; |
||||
} else { |
||||
this.$message({ |
||||
message: '更新失败,请联系管理员', |
||||
type: 'error' |
||||
}); |
||||
} |
||||
|
||||
}, created() { |
||||
|
||||
}, watch: {}, |
||||
computed: {}, mounted() { |
||||
this.$store.dispatch('doappInfoIndex', [[5, 5], [5, 5]]); |
||||
this.getapptimelineFun(); |
||||
}, filters: { |
||||
downcontent(content) { |
||||
if (content) { |
||||
return content |
||||
} else { |
||||
return "修改下载地址" |
||||
} |
||||
}, |
||||
formatdatatimeline: function (timestr) { |
||||
return timestr.split("T")[0]; |
||||
}, |
||||
formattimeline: function (timestr) { |
||||
return timestr.split(".")[0].split("T")[1]; |
||||
}, |
||||
getiOStype: function (type) { |
||||
let ftype = ''; |
||||
if (type === 1) { |
||||
ftype = '内测版' |
||||
} else if (type === 2) { |
||||
ftype = '企业版' |
||||
} |
||||
return ftype |
||||
}, |
||||
}, params |
||||
); |
||||
}, |
||||
make_master_release(app) { |
||||
this.updatereleaseappFun({ |
||||
"methods": "PUT", |
||||
"app_id": this.currentapp.app_id, |
||||
"release_id": app.release_id, |
||||
"data": { |
||||
"make_master": app.release_id |
||||
} |
||||
}); |
||||
|
||||
}, |
||||
endEdit(app, type) { |
||||
if (type === 'changelog') { |
||||
app.editing.changelog = false; |
||||
|
||||
} else if (type === 'binary_url') { |
||||
app.editing.binary_url = false; |
||||
} |
||||
}, |
||||
updateChangelog(app, type) { |
||||
if (type === 'changelog') { |
||||
this.activity.editing.changelog = false; |
||||
this.updatas = {"changelog": app.changelog} |
||||
} else if (type === 'binary_url') { |
||||
this.activity.editing.binary_url = false; |
||||
this.updatas = {"binary_url": app.binary_url} |
||||
} |
||||
this.updatereleaseappFun({ |
||||
"methods": "PUT", |
||||
"app_id": this.currentapp.app_id, |
||||
"release_id": app.release_id, |
||||
"data": this.updatas |
||||
}); |
||||
this.updatas = {} |
||||
}, |
||||
startEdit(app, type) { |
||||
if (type === 'changelog') { |
||||
|
||||
app.editing.changelog = true; |
||||
} else if (type === 'binary_url') { |
||||
app.editing.binary_url = true; |
||||
} |
||||
} |
||||
|
||||
}, created() { |
||||
|
||||
}, watch: {}, |
||||
computed: {}, mounted() { |
||||
this.$store.dispatch('doappInfoIndex', [[5, 5], [5, 5]]); |
||||
this.getAppTimelineFun(); |
||||
}, filters: { |
||||
downcontent(content) { |
||||
if (content) { |
||||
return content |
||||
} else { |
||||
return "修改下载地址" |
||||
} |
||||
}, |
||||
formatdatatimeline: function (timestr) { |
||||
return timestr.split("T")[0]; |
||||
}, |
||||
formattimeline: function (timestr) { |
||||
return timestr.split(".")[0].split("T")[1]; |
||||
}, |
||||
getiOStype: function (type) { |
||||
let ftype = ''; |
||||
if (type === 1) { |
||||
ftype = '内测版' |
||||
} else if (type === 2) { |
||||
ftype = '企业版' |
||||
} |
||||
return ftype |
||||
}, |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style scoped> |
||||
|
||||
|
||||
.directive-view-release { |
||||
position: relative; |
||||
padding-left: 80px; |
||||
color: #9b9b9b; |
||||
} |
||||
|
||||
.directive-view-release > i { |
||||
display: -webkit-box; |
||||
display: -ms-flexbox; |
||||
display: flex; |
||||
height: 50px; |
||||
-webkit-box-align: center; |
||||
-ms-flex-align: center; |
||||
align-items: center; |
||||
-webkit-box-pack: center; |
||||
-ms-flex-pack: center; |
||||
justify-content: center; |
||||
position: absolute; |
||||
left: 0; |
||||
z-index: 2; |
||||
width: 50px; |
||||
border: 1px solid rgba(151, 151, 151, .2); |
||||
border-radius: 50%; |
||||
background-color: #f6f6f6; |
||||
text-align: center; |
||||
font-size: 22px |
||||
} |
||||
|
||||
.directive-view-release > i:before { |
||||
display: inline-block; |
||||
margin-top: 2px; |
||||
margin-left: 2px |
||||
} |
||||
|
||||
.directive-view-release .release-metainfo { |
||||
margin-top: 2px |
||||
} |
||||
|
||||
.directive-view-release .release-metainfo small { |
||||
display: inline-block; |
||||
vertical-align: middle; |
||||
margin: 8px 0; |
||||
line-height: 14px |
||||
} |
||||
|
||||
.directive-view-release .release-metainfo small i, .directive-view-release .release-metainfo small span { |
||||
display: inline-block; |
||||
vertical-align: middle |
||||
} |
||||
|
||||
.directive-view-release .release-metainfo small i { |
||||
margin-right: 2px; |
||||
line-height: 14px |
||||
} |
||||
|
||||
.directive-view-release > b { |
||||
display: inline-block; |
||||
vertical-align: middle; |
||||
margin-right: 30px; |
||||
color: #4a4a4a; |
||||
font-weight: 400; |
||||
font-size: 20px |
||||
} |
||||
|
||||
.directive-view-release pre, .directive-view-release textarea { |
||||
margin: 14px 0; |
||||
padding: 0; |
||||
border: 0; |
||||
background-color: transparent; |
||||
color: #4a4a4a; |
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif |
||||
} |
||||
|
||||
.directive-view-release textarea { |
||||
padding: 12px 16px; |
||||
width: 500px; |
||||
height: 120px; |
||||
border-radius: 5px; |
||||
resize: none; |
||||
border: 1px solid #bdc6c7; |
||||
color: #555; |
||||
font-size: 16px |
||||
} |
||||
|
||||
.directive-view-release .tooltip-top { |
||||
position: relative; |
||||
overflow: visible; |
||||
color: #9b9b9b; |
||||
} |
||||
|
||||
|
||||
.directive-view-release .release-actions { |
||||
margin-top: 10px; |
||||
position: relative |
||||
} |
||||
|
||||
.directive-view-release .release-actions a, .directive-view-release .release-actions button { |
||||
display: inline-block; |
||||
vertical-align: middle; |
||||
margin-right: 8px; |
||||
background-color: transparent; |
||||
border: 1px solid; |
||||
overflow: hidden; |
||||
border-radius: 17px; |
||||
padding: 4px 10px |
||||
} |
||||
|
||||
.directive-view-release .release-actions .tooltip-top { |
||||
overflow: visible; |
||||
position: relative |
||||
} |
||||
|
||||
.directive-view-release .release-actions a i, .directive-view-release .release-actions button i { |
||||
display: inline-block; |
||||
vertical-align: middle |
||||
} |
||||
|
||||
.directive-view-release .release-actions a.btn-save, .directive-view-release .release-actions button.btn-save { |
||||
border-color: #3d6df8; |
||||
background-color: #92c1f8; |
||||
color: #fff |
||||
} |
||||
|
||||
.directive-view-release .release-actions a.btn-cancel, .directive-view-release .release-actions button.btn-cancel { |
||||
border: 0; |
||||
} |
||||
|
||||
.directive-view-release .release-actions a.btn-cancel:hover, .directive-view-release .release-actions button.btn-cancel:hover { |
||||
color: #686868 |
||||
} |
||||
|
||||
.directive-view-release .release-actions a { |
||||
color: #9b9b9b |
||||
} |
||||
|
||||
.directive-view-release .release-actions a:focus, .directive-view-release .release-actions a:hover { |
||||
text-decoration: none |
||||
} |
||||
|
||||
|
||||
.directive-view-release .release-actions .has-text i { |
||||
border-right: 1px solid |
||||
} |
||||
|
||||
.directive-view-release .release-actions.editing { |
||||
margin-top: 0; |
||||
text-align: right; |
||||
width: 500px |
||||
} |
||||
|
||||
.time-line-more { |
||||
background: #F6F6F6; |
||||
border: 1px solid; |
||||
position: relative; |
||||
z-index: 99; |
||||
width: 160px; |
||||
padding: 10px 0; |
||||
border-radius: 40px; |
||||
margin-top: 10px; |
||||
} |
||||
.directive-view-release { |
||||
position: relative; |
||||
padding-left: 80px; |
||||
color: #9b9b9b; |
||||
} |
||||
|
||||
.directive-view-release > i { |
||||
display: -webkit-box; |
||||
display: -ms-flexbox; |
||||
display: flex; |
||||
height: 50px; |
||||
-webkit-box-align: center; |
||||
-ms-flex-align: center; |
||||
align-items: center; |
||||
-webkit-box-pack: center; |
||||
-ms-flex-pack: center; |
||||
justify-content: center; |
||||
position: absolute; |
||||
left: 0; |
||||
z-index: 2; |
||||
width: 50px; |
||||
border: 1px solid rgba(151, 151, 151, .2); |
||||
border-radius: 50%; |
||||
background-color: #f6f6f6; |
||||
text-align: center; |
||||
font-size: 22px |
||||
} |
||||
|
||||
.directive-view-release > i:before { |
||||
display: inline-block; |
||||
margin-top: 2px; |
||||
margin-left: 2px |
||||
} |
||||
|
||||
.directive-view-release .release-metainfo { |
||||
margin-top: 2px |
||||
} |
||||
|
||||
.directive-view-release .release-metainfo small { |
||||
display: inline-block; |
||||
vertical-align: middle; |
||||
margin: 8px 0; |
||||
line-height: 14px |
||||
} |
||||
|
||||
.directive-view-release .release-metainfo small i, .directive-view-release .release-metainfo small span { |
||||
display: inline-block; |
||||
vertical-align: middle |
||||
} |
||||
|
||||
.directive-view-release .release-metainfo small i { |
||||
margin-right: 2px; |
||||
line-height: 14px |
||||
} |
||||
|
||||
.directive-view-release > b { |
||||
display: inline-block; |
||||
vertical-align: middle; |
||||
margin-right: 30px; |
||||
color: #4a4a4a; |
||||
font-weight: 400; |
||||
font-size: 20px |
||||
} |
||||
|
||||
.directive-view-release pre, .directive-view-release textarea { |
||||
margin: 14px 0; |
||||
padding: 0; |
||||
border: 0; |
||||
background-color: transparent; |
||||
color: #4a4a4a; |
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif |
||||
} |
||||
|
||||
.directive-view-release textarea { |
||||
padding: 12px 16px; |
||||
width: 500px; |
||||
height: 120px; |
||||
border-radius: 5px; |
||||
resize: none; |
||||
border: 1px solid #bdc6c7; |
||||
color: #555; |
||||
font-size: 16px |
||||
} |
||||
|
||||
.directive-view-release .tooltip-top { |
||||
position: relative; |
||||
overflow: visible; |
||||
color: #9b9b9b; |
||||
} |
||||
|
||||
|
||||
.directive-view-release .release-actions { |
||||
margin-top: 10px; |
||||
position: relative |
||||
} |
||||
|
||||
.directive-view-release .release-actions a, .directive-view-release .release-actions button { |
||||
display: inline-block; |
||||
vertical-align: middle; |
||||
margin-right: 8px; |
||||
background-color: transparent; |
||||
border: 1px solid; |
||||
overflow: hidden; |
||||
border-radius: 17px; |
||||
padding: 4px 10px |
||||
} |
||||
|
||||
.directive-view-release .release-actions .tooltip-top { |
||||
overflow: visible; |
||||
position: relative |
||||
} |
||||
|
||||
.directive-view-release .release-actions a i, .directive-view-release .release-actions button i { |
||||
display: inline-block; |
||||
vertical-align: middle |
||||
} |
||||
|
||||
.directive-view-release .release-actions a.btn-save, .directive-view-release .release-actions button.btn-save { |
||||
border-color: #3d6df8; |
||||
background-color: #92c1f8; |
||||
color: #fff |
||||
} |
||||
|
||||
.directive-view-release .release-actions a.btn-cancel, .directive-view-release .release-actions button.btn-cancel { |
||||
border: 0; |
||||
} |
||||
|
||||
.directive-view-release .release-actions a.btn-cancel:hover, .directive-view-release .release-actions button.btn-cancel:hover { |
||||
color: #686868 |
||||
} |
||||
|
||||
.directive-view-release .release-actions a { |
||||
color: #9b9b9b |
||||
} |
||||
|
||||
.directive-view-release .release-actions a:focus, .directive-view-release .release-actions a:hover { |
||||
text-decoration: none |
||||
} |
||||
|
||||
|
||||
.directive-view-release .release-actions .has-text i { |
||||
border-right: 1px solid |
||||
} |
||||
|
||||
.directive-view-release .release-actions.editing { |
||||
margin-top: 0; |
||||
text-align: right; |
||||
width: 500px |
||||
} |
||||
|
||||
.time-line-more { |
||||
background: #F6F6F6; |
||||
border: 1px solid; |
||||
position: relative; |
||||
z-index: 99; |
||||
width: 160px; |
||||
padding: 10px 0; |
||||
border-radius: 40px; |
||||
margin-top: 10px; |
||||
} |
||||
</style> |
||||
|
@ -0,0 +1,286 @@ |
||||
<template> |
||||
<transition :name="transitionName"> |
||||
<div> |
||||
<div style="text-align: center"> |
||||
<el-transfer |
||||
id="transfer" |
||||
v-model="choices_data" |
||||
:button-texts="['', '']" |
||||
:data="app_developer_lists" |
||||
:format="{ |
||||
noChecked: '${total}', |
||||
hasChecked: '${checked}/${total}' |
||||
}" |
||||
:left-default-checked="left_data" |
||||
:props="s_props" |
||||
:right-default-checked="right_data" |
||||
:titles="s_titles" |
||||
filterable |
||||
style="text-align: left; display: inline-block" |
||||
@change="handleChange"> |
||||
<div slot-scope="{ option }" style="height: 60px;display: block"> |
||||
<el-popover v-if="app_id" placement="left" trigger="hover"> |
||||
<el-tag v-if="option.app_private_number > 0">专属应用账户,存在其他应用单独使用该开发者</el-tag> |
||||
<el-tag v-else type="info">公共应用账户,所有应用公用此开发者</el-tag> |
||||
<p>开发者ID: {{ option.issuer_id }} </p> |
||||
<p>应用签名数: {{ option.app_used_count }} </p> |
||||
<p>应用签名数限额: {{ option.app_limit_number }} </p> |
||||
<p>已分配专属应用数: {{ option.app_private_number }} </p> |
||||
<p>开发者账户已使用设备数: {{ option.developer_used_number }}</p> |
||||
<p>开发者账户可用设备数: {{ 100 - option.developer_used_number }}</p> |
||||
<p>由于您设置可用设备数: {{ option.usable_number }} ,所以现在可用设备数: {{ |
||||
option.usable_number - option.developer_used_number > 0 |
||||
? option.usable_number - option.developer_used_number : 0 |
||||
}}</p> |
||||
<p>证书到期时间: {{ option.cert_expire_time }}</p> |
||||
<p v-if="option.app_usable_number > 0"> |
||||
分配数量: |
||||
<el-input-number v-model="option.app_usable_number" :max="100" :min="1" |
||||
label="分配数量" size="small"/> |
||||
<el-button size="small" style="margin-left: 10px" @click="saveNumber(option)">保存修改</el-button> |
||||
</p> |
||||
<p>该应用已经消耗 {{ option.app_used_number }} 个设备数</p> |
||||
<p>描述: {{ option.description }}</p> |
||||
<p>账户状态: {{ option.status_display }}</p> |
||||
|
||||
<div slot="reference" class="name-wrapper"> |
||||
<div> |
||||
<el-tag v-if="option.app_used_number>0 && choices_data.indexOf(option.issuer_id)===-1 " size="mini" |
||||
type="warning"> Del |
||||
</el-tag> |
||||
{{ option.issuer_id }} - {{ |
||||
option.usable_number - option.developer_used_number > 0 |
||||
? option.usable_number - option.developer_used_number : 0 |
||||
}} - {{ option.description }} |
||||
</div> |
||||
</div> |
||||
</el-popover> |
||||
<el-popover v-if="issuer_id" placement="left" trigger="hover"> |
||||
<p>应用ID: {{ option.app_id }} </p> |
||||
<p>应用名称: {{ option.name }} </p> |
||||
<p>应用BundleId: {{ option.bundle_id }} </p> |
||||
<p>短连接: {{ option.short }} </p> |
||||
<p v-if="option.app_usable_number>0"> |
||||
分配数量: |
||||
<el-input-number v-model="option.app_usable_number" :max="100" :min="1" |
||||
label="分配数量" size="small"/> |
||||
<el-button size="small" style="margin-left: 10px" @click="saveNumber(option)">保存修改</el-button> |
||||
</p> |
||||
<p>使用数量: {{ option.app_used_number }}</p> |
||||
<p>描述: {{ option.description }}</p> |
||||
<div slot="reference" class="name-wrapper"> |
||||
<div> |
||||
<span v-if="option.app_usable_number>0">{{ option.app_usable_number }} - </span> |
||||
<el-tag v-else-if="option.app_used_number>0" size="mini" type="warning"> Del</el-tag> |
||||
{{ option.name }} - {{ option.bundle_id }} - {{ option.app_id }} |
||||
</div> |
||||
</div> |
||||
</el-popover> |
||||
|
||||
</div> |
||||
<el-button slot="left-footer" class="transfer-footer" @click="getinfos">刷新</el-button> |
||||
<el-button slot="right-footer" class="transfer-footer" @click="saveAppleApps">保存</el-button> |
||||
<el-link v-if="issuer_id" slot="right-footer" :underline="false" style="margin-left: 20px">已经分配 |
||||
{{ app_private_used_number }} 还有 {{ 100 - app_private_used_number }} 可分配使用 |
||||
</el-link> |
||||
</el-transfer> |
||||
</div> |
||||
</div> |
||||
|
||||
</transition> |
||||
</template> |
||||
|
||||
<script> |
||||
import {developerBindAppFun} from "@/restful"; |
||||
import {sort_compare} from "@/utils"; |
||||
import {Loading} from "element-ui"; |
||||
|
||||
export default { |
||||
name: 'AppleDeveloperBindApp', |
||||
props: { |
||||
transitionName: { |
||||
type: String, |
||||
default: 'appledeveloperbind' |
||||
}, |
||||
app_id: { |
||||
type: String, |
||||
default: undefined |
||||
}, |
||||
issuer_id: { |
||||
type: String, |
||||
default: undefined |
||||
}, |
||||
}, |
||||
data() { |
||||
return { |
||||
app_developer_lists: [], |
||||
left_data: [], |
||||
right_data: [], |
||||
choices_data: [], |
||||
choices_data_list: [], |
||||
s_props: {}, |
||||
s_titles: [], |
||||
app_private_used_number: 100, |
||||
app_limit_number: 0, |
||||
}; |
||||
}, |
||||
mounted() { |
||||
this.getinfos() |
||||
}, |
||||
methods: { |
||||
get_choice_data_from_key(key_list) { |
||||
let n_data = []; |
||||
let field = 'app_id' |
||||
if (this.app_id) { |
||||
field = 'issuer_id' |
||||
} |
||||
this.app_private_used_number = 0 |
||||
for (let i = 0; i < this.app_developer_lists.length; i++) { |
||||
for (let j = 0; j < key_list.length; j++) { |
||||
if (key_list[j] === this.app_developer_lists[i][field]) { |
||||
n_data.push(this.app_developer_lists[i]) |
||||
this.app_private_used_number += this.app_developer_lists[i]['app_usable_number'] |
||||
} |
||||
} |
||||
} |
||||
return [n_data, this.app_private_used_number] |
||||
}, |
||||
handleChange(value, direction, movedKeys) { |
||||
if (this.issuer_id && direction === 'right') { |
||||
// 不清楚当时为啥这样写,但是目前当 应用没有进行任何签名的时候,无法选中当前应用 |
||||
// for (let i = 0; i < movedKeys.length; i++) { |
||||
// let app_info = this.get_choice_data_from_key([movedKeys[i]])[0][0] |
||||
// if (!(app_info && app_info.app_used_number > 0)) { |
||||
// this.choices_data.splice(this.choices_data.indexOf(movedKeys[i]), 1) |
||||
// } |
||||
// } |
||||
} |
||||
if (this.app_id && direction === 'right') { |
||||
for (let i = 0; i < movedKeys.length; i++) { |
||||
let developer_info = this.get_choice_data_from_key([movedKeys[i]])[0][0] |
||||
if (!(developer_info && developer_info.app_used_count)) { |
||||
this.choices_data.splice(this.choices_data.indexOf(movedKeys[i]), 1) |
||||
} |
||||
} |
||||
} |
||||
this.get_choice_data_from_key(value) |
||||
}, |
||||
check_used_number() { |
||||
if (this.get_choice_data_from_key(this.choices_data)[1] > 100) { |
||||
this.$message.warning("超出最大分配额度,请注意,尽量保证所有应用分配额度总和为 100") |
||||
} |
||||
}, |
||||
saveNumber(infos) { |
||||
developerBindAppFun(data => { |
||||
if (data.code === 1000) { |
||||
// this.choices_data = this.format_data(data.data) |
||||
} else { |
||||
this.$message.error("数据更新失败" + data.msg) |
||||
} |
||||
this.getinfos() |
||||
}, { |
||||
methods: 'PUT', |
||||
data: {'app_id': this.app_id, 'issuer_id': this.issuer_id, 'infos': infos} |
||||
}) |
||||
}, |
||||
getinfos() { |
||||
if (this.issuer_id) { |
||||
this.s_props = { |
||||
key: 'app_id', |
||||
label: 'name', |
||||
} |
||||
this.getBindInfo({act: 'apps'}) |
||||
// eslint-disable-next-line no-unused-vars |
||||
setTimeout(_ => { |
||||
this.check_used_number() |
||||
}, 1000) |
||||
} else { |
||||
this.s_props = { |
||||
key: 'issuer_id', |
||||
label: 'issuer_id', |
||||
disabled: 'is_disabled' |
||||
} |
||||
this.s_titles = ['可分配签名开发者账户', '已分配签名开发者账户'] |
||||
this.getBindInfo({act: 'developer'}) |
||||
} |
||||
this.getBindInfo({}) |
||||
}, |
||||
saveAppleApps() { |
||||
developerBindAppFun(data => { |
||||
if (data.code === 1000) { |
||||
this.$message.success("数据保存成功") |
||||
} else { |
||||
this.$message.error("数据更新失败" + data.msg) |
||||
} |
||||
this.getinfos() |
||||
}, { |
||||
methods: 'POST', |
||||
data: {'app_id': this.app_id, 'issuer_id': this.issuer_id, 'choices_data': this.choices_data} |
||||
}) |
||||
}, |
||||
getBindInfo(params) { |
||||
let loadingInstance = Loading.service({target: '#transfer'}) |
||||
if (this.issuer_id) { |
||||
params.issuer_id = this.issuer_id |
||||
} |
||||
if (this.app_id) { |
||||
params.app_id = this.app_id |
||||
} |
||||
developerBindAppFun(data => { |
||||
if (data.code === 1000) { |
||||
if (params.act === 'apps' || params.act === 'developer') { |
||||
this.app_developer_lists = data.data |
||||
if (params.act === 'developer') { |
||||
this.app_developer_lists.sort(sort_compare('developer_used_number')) |
||||
} |
||||
if (params.act === 'apps') { |
||||
if (data.app_limit_number) { |
||||
this.app_limit_number = data.app_limit_number |
||||
} |
||||
this.s_titles = ['可分配苹果应用', '已分配苹果应用,最多可以分配' + this.app_limit_number + '个应用'] |
||||
} |
||||
this.get_choice_data_from_key(this.choices_data) |
||||
} else { |
||||
this.choices_data_list = data.data; |
||||
this.choices_data = this.format_data(data.data) |
||||
this.get_choice_data_from_key(this.choices_data) |
||||
} |
||||
} else { |
||||
this.$message.error("数据获取失败" + data.msg) |
||||
} |
||||
this.$nextTick(() => { // 以服务的方式调用的 Loading 需要异步关闭 |
||||
loadingInstance.close() |
||||
}); |
||||
}, {methods: 'GET', data: params}) |
||||
}, |
||||
format_data(data) { |
||||
let n_data = []; |
||||
let field = 'app_id' |
||||
if (this.app_id) { |
||||
field = 'issuer_id' |
||||
} |
||||
this.app_private_used_number = 0 |
||||
if (data && data.length > 0) { |
||||
for (let i = 0; i < data.length; i++) { |
||||
n_data.push(data[i][field]) |
||||
} |
||||
} |
||||
return n_data |
||||
}, |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style scoped> |
||||
/deep/ .el-transfer-panel { |
||||
width: 460px; |
||||
} |
||||
|
||||
/*/deep/ .el-transfer-panel__item {*/ |
||||
/* height: 60px;*/ |
||||
/*}*/ |
||||
.transfer-footer { |
||||
text-align: center; |
||||
float: right; |
||||
} |
||||
</style> |