Compare commits
256 Commits
publicsign
...
master
Author | SHA1 | Date |
---|---|---|
|
e12779d654 | 2 years ago |
|
ac590563a7 | 2 years ago |
|
8fc1d353c9 | 3 years ago |
|
35b64d74de | 3 years ago |
|
a064988f56 | 3 years ago |
|
adff361c11 | 3 years ago |
|
419e39eaaa | 3 years ago |
|
9d9cb3f2cb | 3 years ago |
|
dd802dccbb | 3 years ago |
|
1262bff671 | 3 years ago |
|
289737ed00 | 3 years ago |
|
dc7b491534 | 3 years ago |
|
eed0f5194c | 3 years ago |
|
e0599585be | 3 years ago |
|
42451f2cb0 | 3 years ago |
|
646162593e | 3 years ago |
|
200494fcf3 | 3 years ago |
|
fe5a7605f0 | 3 years ago |
|
f70351d8e5 | 3 years ago |
|
9e2f40383a | 3 years ago |
|
debe95791e | 3 years ago |
|
a3887825c9 | 3 years ago |
|
8a8f9ef7fe | 3 years ago |
|
8e325e6cde | 3 years ago |
|
92961cfa61 | 3 years ago |
|
8c25aab63c | 3 years ago |
|
0cc5084390 | 3 years ago |
|
4d98981485 | 3 years ago |
|
a7a1472533 | 3 years ago |
|
332d12bddf | 3 years ago |
|
6439824468 | 3 years ago |
|
42478f21d9 | 3 years ago |
|
2c67305f8a | 3 years ago |
|
79037d5248 | 3 years ago |
|
525ec097d7 | 3 years ago |
|
a35ca0b087 | 3 years ago |
|
d9ac93ccc1 | 3 years ago |
|
1ff3da6896 | 3 years ago |
|
cbad06e95d | 3 years ago |
|
b093d7133b | 3 years ago |
|
7aa0471ba9 | 3 years ago |
|
2224ce27c7 | 3 years ago |
|
d8b124c1a7 | 3 years ago |
|
d1a5d69ac8 | 3 years ago |
|
8a8d2f2400 | 3 years ago |
|
49832ca702 | 3 years ago |
|
7075bc7ed6 | 3 years ago |
|
7d70f381a1 | 3 years ago |
|
15a506450c | 3 years ago |
|
93c13fa776 | 3 years ago |
|
c8f02465d0 | 3 years ago |
|
2e240735dc | 3 years ago |
|
ec908f0dea | 3 years ago |
|
47abaf61f5 | 3 years ago |
|
31fe8664a9 | 3 years ago |
|
f4ca8d48f9 | 3 years ago |
|
e2b9b12613 | 3 years ago |
|
f772d65765 | 3 years ago |
|
3ad5e03504 | 3 years ago |
|
5f967a9b52 | 3 years ago |
|
e7858a840e | 3 years ago |
|
b191cbae6b | 3 years ago |
|
c36ab08f35 | 3 years ago |
|
a5b73c3695 | 3 years ago |
|
0c6b61327a | 3 years ago |
|
92c0345341 | 3 years ago |
|
25c2ea4c7a | 3 years ago |
|
dfcf213bed | 3 years ago |
|
2b29e0e3bd | 3 years ago |
|
a9bbdd40bd | 3 years ago |
|
97349e758f | 3 years ago |
|
156bf67c1c | 3 years ago |
|
1d75c8ed23 | 3 years ago |
|
ef243feb9f | 3 years ago |
|
58472fb9e4 | 3 years ago |
|
6c25f6a932 | 3 years ago |
|
2d21ee9150 | 3 years ago |
|
04ba947219 | 3 years ago |
|
884d6a47e8 | 3 years ago |
|
0a64689902 | 3 years ago |
|
5ca5b0eb34 | 3 years ago |
|
3bbabdafdb | 3 years ago |
|
4cd0dc7586 | 3 years ago |
|
5eb947843e | 3 years ago |
|
17ab6e6efd | 3 years ago |
|
94bc5cc1db | 3 years ago |
|
584f50ba20 | 3 years ago |
|
df38944eab | 3 years ago |
|
fe880b27b7 | 3 years ago |
|
8316a52595 | 3 years ago |
|
747d2b3dfa | 3 years ago |
|
04ae8cccc4 | 3 years ago |
|
3b8134aafd | 3 years ago |
|
bb9bdf8891 | 3 years ago |
|
bc0cee937d | 3 years ago |
|
d1a41a179b | 3 years ago |
|
3ff322849a | 3 years ago |
|
4184f2ad1c | 3 years ago |
|
22a9b8d816 | 3 years ago |
|
2390397f1b | 3 years ago |
|
ae9dfae6a3 | 3 years ago |
|
d7e3186f9d | 3 years ago |
|
2bfd694f23 | 3 years ago |
|
63e09c1925 | 3 years ago |
|
391e4987de | 3 years ago |
|
88745550d4 | 3 years ago |
|
59e73fa83e | 3 years ago |
|
5eca01278b | 3 years ago |
|
5edf7cd65a | 3 years ago |
|
cf9d9eeaf8 | 3 years ago |
|
c4a4db2c7e | 3 years ago |
|
24a8307164 | 3 years ago |
|
05669b8d3e | 3 years ago |
|
32c3058d57 | 3 years ago |
|
4bbae93933 | 3 years ago |
|
f94184551a | 3 years ago |
|
dd73441bdd | 3 years ago |
|
4e7927a332 | 3 years ago |
|
fc1963c8a9 | 3 years ago |
|
d15b583804 | 3 years ago |
|
d930603919 | 3 years ago |
|
9b9be3fcf9 | 3 years ago |
|
378912944f | 3 years ago |
|
75c7d365a3 | 3 years ago |
|
1dec3b7de2 | 3 years ago |
|
eeba5b409a | 3 years ago |
|
684a407f97 | 3 years ago |
|
5901d63f3e | 3 years ago |
|
cf14dcb0a5 | 3 years ago |
|
e780a2597e | 3 years ago |
|
02f908e3de | 3 years ago |
|
7ceb9c83c1 | 3 years ago |
|
77d97fd1d2 | 3 years ago |
|
98fe1d5f61 | 3 years ago |
|
fb77c251c3 | 3 years ago |
|
c765658fb5 | 3 years ago |
|
dd1fb29ba0 | 3 years ago |
|
d571b399d7 | 3 years ago |
|
115d1c95df | 3 years ago |
|
e54f6c1286 | 3 years ago |
|
75fecbca10 | 3 years ago |
|
96295132d9 | 3 years ago |
|
ec327598a2 | 3 years ago |
|
81db86b9ef | 3 years ago |
|
6076659bf1 | 3 years ago |
|
4b90ce682b | 3 years ago |
|
f00135a6a4 | 3 years ago |
|
8ce3b14475 | 3 years ago |
|
25d09e8cf1 | 3 years ago |
|
c6e78a6eab | 3 years ago |
|
e9c6cadeb6 | 3 years ago |
|
153f800b91 | 3 years ago |
|
5e380fa09e | 3 years ago |
|
42bab0739b | 3 years ago |
|
518fc3101e | 3 years ago |
|
875a3a4305 | 3 years ago |
|
6051f443c1 | 3 years ago |
|
c4fd9aa793 | 3 years ago |
|
9ba02e449d | 3 years ago |
|
cb841b5cf7 | 3 years ago |
|
9353abc8a9 | 3 years ago |
|
06bace9f66 | 3 years ago |
|
ce31dd5621 | 3 years ago |
|
91e042ea1d | 3 years ago |
|
f02eb026de | 3 years ago |
|
44cfd03cee | 3 years ago |
|
14f60d4f8d | 3 years ago |
|
614db12422 | 3 years ago |
|
10ab90a104 | 3 years ago |
|
f5ffc3632f | 3 years ago |
|
adc71de160 | 3 years ago |
|
6f959fa4a9 | 3 years ago |
|
3d2ce3b73d | 3 years ago |
|
192d4cadc0 | 3 years ago |
|
9f2fea094d | 3 years ago |
|
32bdc4ba9e | 3 years ago |
|
fdd0abb07e | 3 years ago |
|
a580dddd83 | 3 years ago |
|
2f32b71b2b | 3 years ago |
|
03a6202ee2 | 3 years ago |
|
7e15211fd2 | 3 years ago |
|
ae58a71ee4 | 3 years ago |
|
b270d8e5c6 | 3 years ago |
|
32ca967d07 | 4 years ago |
|
878183dbce | 4 years ago |
|
bebc8417eb | 4 years ago |
|
de511bf90c | 4 years ago |
|
a8c1df58ee | 4 years ago |
|
ef335e118a | 4 years ago |
|
03f66df7b9 | 4 years ago |
|
4d4ee64a65 | 4 years ago |
|
04ccfe77a3 | 4 years ago |
|
d085d86a26 | 4 years ago |
|
8a60be6f4f | 4 years ago |
|
869d5ee7bb | 4 years ago |
|
9572382a9e | 4 years ago |
|
7ad5bc8161 | 4 years ago |
|
59d7d905d3 | 4 years ago |
|
c361d740bf | 4 years ago |
|
17c1f0612a | 4 years ago |
|
2b5325ff32 | 4 years ago |
|
09257733f8 | 4 years ago |
|
5dd1dd0681 | 4 years ago |
|
979b6f0386 | 4 years ago |
|
e8e6ea962a | 4 years ago |
|
c50005e7c7 | 4 years ago |
|
465aea9744 | 4 years ago |
|
7c2a29b86d | 4 years ago |
|
f8418f6414 | 4 years ago |
|
def6c9dfc8 | 4 years ago |
|
205505cb0e | 4 years ago |
|
106ae636a2 | 4 years ago |
|
2e96183c06 | 4 years ago |
|
216bc367c4 | 4 years ago |
|
e559267de3 | 4 years ago |
|
f04c4411c7 | 4 years ago |
|
a60a7d6011 | 4 years ago |
|
d3fc7327a6 | 4 years ago |
|
4decc14bf8 | 4 years ago |
|
d657c709f6 | 4 years ago |
|
73d783b97d | 4 years ago |
|
b18dfa7a14 | 4 years ago |
|
0d26e5ac7b | 4 years ago |
|
bda9cf994d | 4 years ago |
|
9d0d36ca63 | 4 years ago |
|
26e6efeaf4 | 4 years ago |
|
49c35275b6 | 4 years ago |
|
92ba4fc258 | 4 years ago |
|
c8a69acb84 | 4 years ago |
|
7932dde3b4 | 4 years ago |
|
55f5f65e15 | 4 years ago |
|
fd43dcfea4 | 4 years ago |
|
4c41efa46f | 4 years ago |
|
d3e0c53b8f | 4 years ago |
|
bd77da66b7 | 4 years ago |
|
ebed9b1aa4 | 4 years ago |
|
0c5c4a6ce7 | 4 years ago |
|
b3899d4a97 | 4 years ago |
|
27b8a21556 | 4 years ago |
|
bbf9664fc7 | 4 years ago |
|
86467ef2fd | 4 years ago |
|
2aedb458ee | 4 years ago |
|
2e491db16c | 4 years ago |
|
8a59b8d329 | 4 years ago |
|
fce8a09d5e | 4 years ago |
|
29328d293b | 4 years ago |
|
2ec7fb05eb | 4 years ago |
|
341cf21367 | 4 years ago |
|
6412e36d0b | 4 years ago |
|
8bf925e9df | 4 years ago |
|
d550d20998 | 4 years ago |
|
c170086609 | 4 years ago |
|
bd8c8d00cc | 4 years ago |
|
a2c5d1bd3f | 4 years ago |
|
169347ca16 | 4 years ago |
|
372455bcb3 | 4 years ago |
@ -1,144 +1,63 @@ |
|||||||
##### 从git上面下载源码 |
### 用与应用分发,苹果超级签名 |
||||||
``` |
#### 部署前准备 |
||||||
cd /data/ |
- 备案域名【至少需要一个域名,以下可通过子域名部署】 |
||||||
git clone https://github.com/nineaiyu/FlyApps |
- API域名 |
||||||
``` |
- 前端web域名 |
||||||
|
- 下载页域名 |
||||||
#### 超级签名依赖部署 |
- 下载页域名可配置多个 |
||||||
##### fastlane [相关文档](https://github.com/fastlane/fastlane/blob/master/spaceship/docs/DeveloperPortal.md) |
- 存储域名(使用阿里云oss存储) |
||||||
``` |
- ssl证书 |
||||||
# fastlane |
- API域名证书 |
||||||
#1 gem ruby安装 |
- 存储域名证书(使用阿里云oss存储) |
||||||
yum install gem -y |
- 前端web域名证书(可选) |
||||||
yum install ruby-devel -y |
- Centos8Stream 服务器 |
||||||
yum install gcc gcc-c++ -y |
- 如果使用oss存储,则带宽为1M,若使用本地存储,则带宽越大越好 |
||||||
|
- 如果使用超级签,最低配置为2cpu 4G内存,若干不使用签名,则1cpu2G就行 |
||||||
#gem修改为国内镜像 |
- 阿里云短信或极光短信服务【可选一个,主要用与注册,重置密码】 |
||||||
gem sources --add https://gems.ruby-china.com/ --remove https://rubygems.org/ |
- 阿里云短信 |
||||||
|
- 极光短信 |
||||||
gem sources -l |
- 邮箱服务【可选,用与注册,重置密码,通知信息】 |
||||||
#https://gems.ruby-china.com |
- 阿里云OSS存储【可选】 |
||||||
#确保只有 gems.ruby-china.com |
- [sts授权配置](https://help.aliyun.com/document_detail/100624.html) |
||||||
|
- 阿里云CDN【可选,用与加速访问】 |
||||||
#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 |
- 阿里云服务器需要1cpu 2G内存,无需系统盘,如果使用超级签,可以适当增加配置 |
||||||
source /etc/profile.d/rvm.sh |
- 需要阿里云OSS存储和阿里云CDN,并且OSS存储和阿里云服务器部署同一个地区 |
||||||
rvm list known |
- 可以申请一个极验进行滑动验证,或者开启验证码验证 |
||||||
rvm install 2.7 |
- 阿里云备案域名:api和前端可以使用一个域名,下载页单独域名 |
||||||
|
|
||||||
#3 安装fastlane |
#### 部署必备资料 |
||||||
gem install fastlane |
- 域名证书 |
||||||
gem install pry |
- web域名和证书 |
||||||
|
- api域名和证书 |
||||||
# 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 #注释掉,要不然会报错 |
- 本地存储,则该域名和证书可以和api域名证书一致 |
||||||
|
- 阿里云oss存储 |
||||||
``` |
- 开启cdn,需要新域名和证书 |
||||||
##### isign |
- 不开启,无需域名和证书 |
||||||
``` |
- Centos8Stream 服务器 |
||||||
# python2.7 |
|
||||||
yum update python -y |
## 部署方式 |
||||||
pip install -U setuptools pip |
|
||||||
|
### 1.[Docker 部署](./doc/docker.md) 【推荐】 |
||||||
wget https://github.com/nineaiyu/isign/archive/v1.8.0.tar.gz |
|
||||||
tar xvf v1.8.0.tar.gz |
### 2.[本地部署](./doc/local.md) |
||||||
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 |
|
||||||
|
|
||||||
``` |
|
@ -1,12 +0,0 @@ |
|||||||
#!/bin/bash |
|
||||||
# |
|
||||||
# |
|
||||||
# shellcheck disable=SC2006 |
|
||||||
s_path=`pwd` |
|
||||||
|
|
||||||
#first build fir_client |
|
||||||
docker pull node:14.17.3 |
|
||||||
\cp -a build_client.sh fir_client/ |
|
||||||
docker run --rm -v "${s_path}"/fir_client:/fir_client -it node:14.17.3 sh /fir_client/build_client.sh |
|
||||||
|
|
||||||
cd "${s_path}"/fir_ser/ && docker build . -t flyapps |
|
@ -1,7 +0,0 @@ |
|||||||
#!/bin/bash |
|
||||||
# |
|
||||||
# |
|
||||||
|
|
||||||
cd /fir_client/ && yarn config set registry https://registry.npm.taobao.org && yarn install && yarn build |
|
||||||
|
|
||||||
|
|
@ -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 |
@ -1,51 +0,0 @@ |
|||||||
##### 从git上面下载源码 |
|
||||||
``` |
|
||||||
cd /data/ |
|
||||||
git clone https://github.com/nineaiyu/FlyApps |
|
||||||
``` |
|
||||||
|
|
||||||
#### docker环境安装 [centos7] |
|
||||||
``` |
|
||||||
yum install epel-release -y |
|
||||||
yum clean all && yum makecache |
|
||||||
yum install docker -y |
|
||||||
|
|
||||||
``` |
|
||||||
#### 配置域名和证书,如果有cdn或者oss,也要进行配置 |
|
||||||
```shell script |
|
||||||
nginx.conf.d/app.hehelucky.cn.key |
|
||||||
nginx.conf.d/app.hehelucky.cn.pem |
|
||||||
nginx.conf.d/flyapps-vhost.conf |
|
||||||
``` |
|
||||||
### api服务需要修改api和web域名,短信,邮箱,geetest,存储等信息 |
|
||||||
```shell script |
|
||||||
vim fir_ser/config.py |
|
||||||
|
|
||||||
API_DOMAIN = "https://app.hehelucky.cn" |
|
||||||
WEB_DOMAIN = "https://app.hehelucky.cn" |
|
||||||
MOBILEPROVISION = "https://ali-static.jappstore.com/embedded.mobileprovision" |
|
||||||
|
|
||||||
``` |
|
||||||
### web页面需要修改指定api域名 |
|
||||||
```vuejs |
|
||||||
vim fir_client/vue.config.js |
|
||||||
|
|
||||||
const pro_base_env = { |
|
||||||
baseUrl: 'https://flyapps.cn', |
|
||||||
index_static: 'https://static.flyapps.cn/index/', |
|
||||||
baseShortUrl: 'https://flyapps.top', |
|
||||||
short_static: 'https://static.flyapps.top/short/', |
|
||||||
}; |
|
||||||
``` |
|
||||||
|
|
||||||
##### 构建静态资源和api服务 |
|
||||||
``` |
|
||||||
sh build.sh |
|
||||||
``` |
|
||||||
|
|
||||||
|
|
||||||
##### 启动所有服务 |
|
||||||
``` |
|
||||||
sh start.sh |
|
||||||
``` |
|
||||||
|
|
@ -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,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> |
After Width: | Height: | Size: 71 KiB |
Before Width: | Height: | Size: 22 KiB |
@ -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> |
@ -0,0 +1,470 @@ |
|||||||
|
<template> |
||||||
|
<el-main> |
||||||
|
|
||||||
|
<el-dialog |
||||||
|
:close-on-click-modal="false" |
||||||
|
:close-on-press-escape="false" |
||||||
|
:visible.sync="configVisible" |
||||||
|
center |
||||||
|
title="下载页部署配置" |
||||||
|
width="666px"> |
||||||
|
|
||||||
|
|
||||||
|
<el-card v-for="info in config_lists" :key="info.key" class="box-card" shadow="hover" |
||||||
|
style="margin-bottom: 20px"> |
||||||
|
<div slot="header" class="clearfix"> |
||||||
|
<span><el-tag size="medium" type="info">配置KEY</el-tag> <el-tag size="medium">{{ info.key }}</el-tag></span> |
||||||
|
<div style="float: right"> |
||||||
|
<el-switch |
||||||
|
v-model="info.value" |
||||||
|
active-color="#13ce66" |
||||||
|
active-text="启用" |
||||||
|
active-value="true" |
||||||
|
inactive-color="#ff4949" |
||||||
|
inactive-text="关闭" |
||||||
|
inactive-value="false" |
||||||
|
@change="changeConfig(info)"> |
||||||
|
</el-switch> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<el-tag size="medium" type="info">描述信息</el-tag> |
||||||
|
{{ info.title }} |
||||||
|
</el-card> |
||||||
|
<el-divider></el-divider> |
||||||
|
<el-card style="margin-top: 20px"> |
||||||
|
<div slot="header" class="clearfix"> |
||||||
|
<el-tag size="medium" type="success">下载页源码及操作文档</el-tag> |
||||||
|
</div> |
||||||
|
<div v-if="short_download_list.length>0"> |
||||||
|
<div style="margin: 10px" v-for="short_download_uri in short_download_list" :key="short_download_uri.key"> |
||||||
|
<el-tag size="medium" type="info">{{short_download_uri.title}}</el-tag> |
||||||
|
<el-link style="margin-left: 10px" :href="short_download_uri.value" target="_blank">点击下载</el-link> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</el-card> |
||||||
|
|
||||||
|
<div slot="footer" class="dialog-footer"> |
||||||
|
<el-button @click="updateConfig">恢复默认值</el-button> |
||||||
|
<el-button @click="configVisible=false">取消</el-button> |
||||||
|
</div> |
||||||
|
|
||||||
|
</el-dialog> |
||||||
|
|
||||||
|
<el-dialog |
||||||
|
:close-on-click-modal="false" |
||||||
|
:close-on-press-escape="false" |
||||||
|
:visible.sync="addCnameVisible" |
||||||
|
center |
||||||
|
title="添加下载页服务器域名" |
||||||
|
width="800px"> |
||||||
|
|
||||||
|
<el-steps :active="p_active" finish-status="success" :align-center="true"> |
||||||
|
<el-step title="添加服务器域名"></el-step> |
||||||
|
<el-step title="验证服务器域名所有权"></el-step> |
||||||
|
<el-step title="添加成功"></el-step> |
||||||
|
</el-steps> |
||||||
|
|
||||||
|
<el-container> |
||||||
|
|
||||||
|
<div v-if="p_active===0" style="margin-top: 20px"> |
||||||
|
<el-tag style="margin: 10px 5px">1.如果是cdn等含有CNAME,直接添加cdn的 CNAME 值</el-tag> |
||||||
|
<el-tag style="margin: 10px 5px">2.如果是服务器,需要将域名解析到服务器,然后添加该解析的域名</el-tag> |
||||||
|
<div style="width: 600px;text-align: center;margin: auto"> |
||||||
|
|
||||||
|
<el-form ref="form" :model="addSerInfo" label-width="120px"> |
||||||
|
|
||||||
|
<el-form-item label="下载服务器域名"> |
||||||
|
<el-input v-model="addSerInfo.domain_record" placeholder="cdn的cname或者服务器的域名,必填"></el-input> |
||||||
|
</el-form-item> |
||||||
|
|
||||||
|
<el-form-item label="下载服务器地址"> |
||||||
|
<el-input v-model="addSerInfo.ip_address" placeholder="如果有服务器地址,添加服务器ip,否则填写服务器域名"></el-input> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item label="备注"> |
||||||
|
<el-input type="textarea" v-model="addSerInfo.description"></el-input> |
||||||
|
</el-form-item> |
||||||
|
</el-form> |
||||||
|
<div style="margin-top: 20px;"> |
||||||
|
<el-button type="primary" @click="addCnameSer">下一步</el-button> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
</div> |
||||||
|
|
||||||
|
<div v-else-if="p_active===1" style="margin-top: 30px;text-align: center"> |
||||||
|
|
||||||
|
请联系域名管理员,前往 <strong>{{ cnameInfo.domain_record }}</strong> 域名 DNS 管理后台添加如下 {{ cnameInfo.r_type }} 记录。 |
||||||
|
<el-table |
||||||
|
:data="domain_tData" |
||||||
|
border |
||||||
|
stripe |
||||||
|
v-loading="loading" |
||||||
|
style="width: 100%;margin-top: 20px"> |
||||||
|
<el-table-column |
||||||
|
align="center" |
||||||
|
label="记录类型" |
||||||
|
prop="r_type" |
||||||
|
width="100"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column |
||||||
|
align="center" |
||||||
|
label="主机记录" |
||||||
|
prop="host_r" |
||||||
|
> |
||||||
|
<template slot-scope="scope"> |
||||||
|
<el-tooltip content="点击复制到剪贴板"> |
||||||
|
<el-link v-if="scope.row.host_r" v-clipboard:copy="scope.row.host_r" |
||||||
|
v-clipboard:success="copy_success" |
||||||
|
:underline="false">{{ scope.row.host_r }} |
||||||
|
</el-link> |
||||||
|
</el-tooltip> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column |
||||||
|
align="center" |
||||||
|
label="记录值" |
||||||
|
prop="cname_r" |
||||||
|
width="300"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
<el-tooltip content="点击复制到剪贴板"> |
||||||
|
<el-link v-if="scope.row.cname_r" v-clipboard:copy="scope.row.cname_r" |
||||||
|
v-clipboard:success="copy_success" |
||||||
|
:underline="false">{{ scope.row.cname_r }} |
||||||
|
</el-link> |
||||||
|
</el-tooltip> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
</el-table> |
||||||
|
<el-alert :closable="false" |
||||||
|
show-icon |
||||||
|
style="margin-top: 30px" |
||||||
|
title="请在域名DNS配置成功后,点击“下一步”按钮" |
||||||
|
type="warning"/> |
||||||
|
|
||||||
|
<div style="margin-top: 20px;text-align: center;"> |
||||||
|
<el-button type="primary" @click="p_active=0">上一步</el-button> |
||||||
|
<el-button type="primary" @click="checkCnameSer" :disabled="loading">下一步</el-button> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</el-container> |
||||||
|
|
||||||
|
|
||||||
|
</el-dialog> |
||||||
|
|
||||||
|
|
||||||
|
<div> |
||||||
|
<el-input |
||||||
|
v-model="search_key" |
||||||
|
clearable |
||||||
|
placeholder="输入下载服务器域名" |
||||||
|
style="width: 30%;margin-right: 30px;margin-bottom: 5px"/> |
||||||
|
<el-button icon="el-icon-search" type="primary" @click="handleCurrentChange(1)"> |
||||||
|
搜索 |
||||||
|
</el-button> |
||||||
|
<div style="float: right"> |
||||||
|
|
||||||
|
|
||||||
|
<el-tooltip content="下载页配置,可以定制部署私有下载页"> |
||||||
|
<el-button plain type="primary" @click="configFun"> |
||||||
|
下载页配置 |
||||||
|
</el-button> |
||||||
|
</el-tooltip> |
||||||
|
<el-button plain type="primary" @click="addDownloadSer"> |
||||||
|
添加下载页服务器 |
||||||
|
</el-button> |
||||||
|
</div> |
||||||
|
|
||||||
|
<el-table |
||||||
|
v-loading="loading" |
||||||
|
:data="cname_info_list" |
||||||
|
border |
||||||
|
stripe |
||||||
|
style="width: 100%"> |
||||||
|
|
||||||
|
<el-table-column |
||||||
|
align="center" |
||||||
|
fixed |
||||||
|
label="下载服务器域名" |
||||||
|
prop="domain_name"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
<el-tooltip content="点击复制到剪贴板"> |
||||||
|
<el-link v-if="scope.row.domain_record" v-clipboard:copy="scope.row.domain_record" |
||||||
|
v-clipboard:success="copy_success" |
||||||
|
:underline="false">{{ scope.row.domain_record }} |
||||||
|
</el-link> |
||||||
|
</el-tooltip> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
|
||||||
|
<el-table-column |
||||||
|
align="center" |
||||||
|
label="下载服务器地址" |
||||||
|
prop="ip_address"> |
||||||
|
</el-table-column> |
||||||
|
|
||||||
|
<el-table-column |
||||||
|
align="center" |
||||||
|
label="状态" |
||||||
|
prop="is_enable" |
||||||
|
width="110"> |
||||||
|
|
||||||
|
<template slot-scope="scope"> |
||||||
|
<el-tooltip v-if="scope.row.is_enable === true" content="已经绑定成功" placement="left-start"> |
||||||
|
<el-button size="small" type="success">成功 |
||||||
|
</el-button> |
||||||
|
</el-tooltip> |
||||||
|
<el-tooltip v-else content="点击激活服务器域名绑定信息" placement="left-start"> |
||||||
|
<el-button size="small" type="warning" @click="continueBind(scope.row)">继续绑定 |
||||||
|
</el-button> |
||||||
|
</el-tooltip> |
||||||
|
|
||||||
|
</template> |
||||||
|
|
||||||
|
</el-table-column> |
||||||
|
|
||||||
|
<el-table-column |
||||||
|
:formatter="format_create_time" |
||||||
|
align="center" |
||||||
|
label="域名绑定时间" |
||||||
|
prop="created_time" |
||||||
|
width="170" |
||||||
|
> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column |
||||||
|
align="center" |
||||||
|
label="备注" |
||||||
|
prop="description"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column |
||||||
|
align="center" |
||||||
|
label="操作" |
||||||
|
prop="is_enable" |
||||||
|
width="100"> |
||||||
|
|
||||||
|
<template slot-scope="scope"> |
||||||
|
<el-tooltip content="删除该下载页服务器" placement="left-start"> |
||||||
|
<el-button size="small" type="danger" @click="delCnameSer(scope.row)">删除 |
||||||
|
</el-button> |
||||||
|
</el-tooltip> |
||||||
|
|
||||||
|
</template> |
||||||
|
|
||||||
|
</el-table-column> |
||||||
|
</el-table> |
||||||
|
|
||||||
|
|
||||||
|
</div> |
||||||
|
<div style="margin-top: 20px;margin-bottom: 20px"> |
||||||
|
<el-pagination |
||||||
|
:current-page.sync="pagination.currentPage" |
||||||
|
:page-size="pagination.pagesize" |
||||||
|
:page-sizes="[10, 20, 50, 100]" |
||||||
|
:total="pagination.total" |
||||||
|
layout="total,sizes, prev, pager, next" |
||||||
|
@size-change="handleSizeChange" |
||||||
|
@current-change="handleCurrentChange"> |
||||||
|
</el-pagination> |
||||||
|
</div> |
||||||
|
</el-main> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
|
||||||
|
import {dCnameInfoFun, personalConfigInfo} from "@/restful"; |
||||||
|
import {getUserInfoFun} from '@/utils' |
||||||
|
import {format_time} from "@/utils/base/utils"; |
||||||
|
|
||||||
|
export default { |
||||||
|
name: "FirUserDomain", |
||||||
|
data() { |
||||||
|
return { |
||||||
|
addSerInfo: {}, |
||||||
|
cnameInfo: {}, |
||||||
|
domain_tData: [], |
||||||
|
p_active: 0, |
||||||
|
cname_info_list: [], |
||||||
|
search_key: "", |
||||||
|
pagination: {"currentPage": 1, "total": 0, "pagesize": 10}, |
||||||
|
loading: false, |
||||||
|
configVisible: false, |
||||||
|
addCnameVisible: false, |
||||||
|
config_lists: [], |
||||||
|
short_download_list: [] |
||||||
|
} |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
continueBind(cname_info) { |
||||||
|
this.addSerInfo = cname_info |
||||||
|
this.addCnameVisible = true |
||||||
|
this.addCnameSer() |
||||||
|
}, |
||||||
|
delCnameSer(cname_info) { |
||||||
|
this.$confirm('若下载域名绑定到该解析,同时也会删除绑定的下载域名,是否继续删除?', '警告', { |
||||||
|
confirmButtonText: '确定', |
||||||
|
cancelButtonText: '取消', |
||||||
|
type: 'warning' |
||||||
|
}).then(() => { |
||||||
|
dCnameInfoFun(data => { |
||||||
|
if (data.code === 1000) { |
||||||
|
this.$message.success("删除成功") |
||||||
|
this.get_data_from_tabname(); |
||||||
|
} else { |
||||||
|
this.$message.error("操作失败了 " + data.msg) |
||||||
|
} |
||||||
|
}, { |
||||||
|
methods: 'DELETE', |
||||||
|
data: {'domain_record': cname_info.domain_record} |
||||||
|
}) |
||||||
|
}) |
||||||
|
}, |
||||||
|
checkCnameSer() { |
||||||
|
this.loading=true |
||||||
|
dCnameInfoFun(data => { |
||||||
|
this.loading=false |
||||||
|
if (data.code === 1000) { |
||||||
|
this.$message.success(this.addSerInfo.domain_record + " 添加成功") |
||||||
|
this.get_data_from_tabname(); |
||||||
|
this.addDownloadSer() |
||||||
|
this.addCnameVisible = false |
||||||
|
} else { |
||||||
|
this.$message.error("操作失败了 " + data.msg) |
||||||
|
} |
||||||
|
}, { |
||||||
|
methods: 'PUT', |
||||||
|
data: {'act': 'check', 'domain_record': this.addSerInfo.domain_record} |
||||||
|
}) |
||||||
|
}, |
||||||
|
addCnameSer() { |
||||||
|
let domain_record = this.addSerInfo.domain_record |
||||||
|
let ip_address = this.addSerInfo.ip_address |
||||||
|
if (domain_record && domain_record.length > 6 && ip_address && ip_address.length > 6) { |
||||||
|
dCnameInfoFun(data => { |
||||||
|
if (data.code === 1000) { |
||||||
|
this.p_active = 1 |
||||||
|
this.cnameInfo = data.data |
||||||
|
this.domain_tData = [this.cnameInfo] |
||||||
|
} else { |
||||||
|
this.$message.error("操作失败了 " + data.msg) |
||||||
|
} |
||||||
|
}, { |
||||||
|
methods: 'POST', |
||||||
|
data: this.addSerInfo |
||||||
|
}) |
||||||
|
} else { |
||||||
|
this.$message.error("参数有误") |
||||||
|
} |
||||||
|
|
||||||
|
}, |
||||||
|
addDownloadSer() { |
||||||
|
this.addSerInfo = {} |
||||||
|
this.cnameInfo = {} |
||||||
|
this.p_active = 0 |
||||||
|
this.addCnameVisible = true |
||||||
|
}, |
||||||
|
configFun() { |
||||||
|
personalConfigInfo(data => { |
||||||
|
if (data.code === 1000) { |
||||||
|
this.short_download_list = data.data |
||||||
|
} else { |
||||||
|
this.$message.error("获取数据失败了 " + data.msg) |
||||||
|
} |
||||||
|
}, { |
||||||
|
methods: 'GET' |
||||||
|
}, 'short_download_uri') |
||||||
|
|
||||||
|
|
||||||
|
personalConfigInfo(data => { |
||||||
|
if (data.code === 1000) { |
||||||
|
this.config_lists = data.data |
||||||
|
this.configVisible = true |
||||||
|
} else { |
||||||
|
this.$message.error("获取数据失败了 " + data.msg) |
||||||
|
} |
||||||
|
}, { |
||||||
|
methods: 'GET' |
||||||
|
}, 'preview_route') |
||||||
|
}, |
||||||
|
changeConfig(info) { |
||||||
|
personalConfigInfo(data => { |
||||||
|
if (data.code === 1000) { |
||||||
|
this.$message.success("操作成功") |
||||||
|
this.configFun() |
||||||
|
} else { |
||||||
|
this.$message.error("操作失败了 " + data.msg) |
||||||
|
} |
||||||
|
}, { |
||||||
|
methods: 'PUT', data: {config_key: info.key, config_value: info.value} |
||||||
|
}, 'preview_route') |
||||||
|
}, |
||||||
|
updateConfig() { |
||||||
|
personalConfigInfo(data => { |
||||||
|
if (data.code === 1000) { |
||||||
|
this.$message.success("操作成功") |
||||||
|
this.configFun() |
||||||
|
} else { |
||||||
|
this.$message.error("操作失败了 " + data.msg) |
||||||
|
} |
||||||
|
}, { |
||||||
|
methods: 'DELETE' |
||||||
|
}, 'preview_route') |
||||||
|
}, |
||||||
|
|
||||||
|
copy_success() { |
||||||
|
this.$message.success('复制剪切板成功'); |
||||||
|
}, |
||||||
|
handleSizeChange(val) { |
||||||
|
this.pagination.pagesize = val; |
||||||
|
this.get_data_from_tabname({ |
||||||
|
"size": this.pagination.pagesize, |
||||||
|
"page": 1 |
||||||
|
}) |
||||||
|
}, |
||||||
|
handleCurrentChange(val) { |
||||||
|
this.pagination.currentPage = val; |
||||||
|
this.get_data_from_tabname({ |
||||||
|
"size": this.pagination.pagesize, |
||||||
|
"page": this.pagination.currentPage |
||||||
|
}) |
||||||
|
}, |
||||||
|
|
||||||
|
get_data_from_tabname(data = {}) { |
||||||
|
data.search_key = this.search_key.replace(/^\s+|\s+$/g, ""); |
||||||
|
this.UserCnameInfoFun(data) |
||||||
|
}, |
||||||
|
UserCnameInfoFun(params) { |
||||||
|
this.loading = true; |
||||||
|
dCnameInfoFun(data => { |
||||||
|
if (data.code === 1000) { |
||||||
|
this.cname_info_list = data.data; |
||||||
|
this.pagination.total = data.count; |
||||||
|
|
||||||
|
} else { |
||||||
|
this.$message.error("域名绑定信息获取失败") |
||||||
|
} |
||||||
|
this.loading = false; |
||||||
|
}, {methods: 'GET', data: params}) |
||||||
|
}, |
||||||
|
|
||||||
|
format_create_time(row) { |
||||||
|
return format_time(row.created_time) |
||||||
|
}, |
||||||
|
|
||||||
|
}, mounted() { |
||||||
|
getUserInfoFun(this); |
||||||
|
this.get_data_from_tabname(); |
||||||
|
} |
||||||
|
} |
||||||
|
</script> |
||||||
|
|
||||||
|
<style scoped> |
||||||
|
.el-main { |
||||||
|
margin: 20px auto 100px; |
||||||
|
width: 1166px; |
||||||
|
position: relative; |
||||||
|
padding-bottom: 1px; |
||||||
|
color: #9b9b9b; |
||||||
|
-webkit-font-smoothing: antialiased; |
||||||
|
border-radius: 1%; |
||||||
|
} |
||||||
|
|
||||||
|
</style> |
@ -0,0 +1,733 @@ |
|||||||
|
<template> |
||||||
|
<el-main> |
||||||
|
<el-dialog :close-on-click-modal="false" :destroy-on-close="true" :title="title" |
||||||
|
:visible.sync="dialogReceiverVisible" width="780px"> |
||||||
|
|
||||||
|
<el-form ref="recevierform" :model="addreceiverinfo" |
||||||
|
label-width="80px" style="margin:0 auto;"> |
||||||
|
|
||||||
|
|
||||||
|
<el-form-item label="姓名"> |
||||||
|
<el-input v-model="addreceiverinfo.receiver_name"/> |
||||||
|
</el-form-item> |
||||||
|
|
||||||
|
<el-form-item label="邮箱"> |
||||||
|
<el-input v-model="addreceiverinfo.email"/> |
||||||
|
</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="addreceiverinfo.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="addreceiverinfo.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 label="微信"> |
||||||
|
<el-tag v-if="addreceiverinfo.wxopenid && addreceiverinfo.wxopenid.length > 6"> |
||||||
|
{{ addreceiverinfo.wxopenid }} |
||||||
|
</el-tag> |
||||||
|
<el-popover v-else |
||||||
|
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" @click="wxLogin">绑定微信</el-button> |
||||||
|
</el-popover> |
||||||
|
</el-form-item> |
||||||
|
|
||||||
|
<el-form-item label="备注"> |
||||||
|
<el-input v-model="addreceiverinfo.description"/> |
||||||
|
</el-form-item> |
||||||
|
|
||||||
|
<el-button @click="saveReceiver">保存</el-button> |
||||||
|
<el-button @click="cancelReceiver">取消</el-button> |
||||||
|
</el-form> |
||||||
|
</el-dialog> |
||||||
|
|
||||||
|
|
||||||
|
<el-dialog :close-on-click-modal="false" :destroy-on-close="true" :visible.sync="dialogChangeReceiverVisible" |
||||||
|
title="修改消息接收人"> |
||||||
|
|
||||||
|
<div style="text-align: left;margin-bottom: 10px"> |
||||||
|
<div style="margin-bottom: 10px"> |
||||||
|
<el-tag type="warning">提醒:如果以下消息接收人的信息有变更,请到“消息接收人管理”中进行修改。</el-tag> |
||||||
|
</div> |
||||||
|
消息类型:{{ notifyConfigMsg.message_type }} - {{ notifyConfigMsg.config_name }} |
||||||
|
</div> |
||||||
|
<el-table |
||||||
|
ref="multipleTable" |
||||||
|
:data="receiver_info_lists" |
||||||
|
border |
||||||
|
stripe |
||||||
|
style="width: 100%" |
||||||
|
@selection-change="handleSelectionChange"> |
||||||
|
<el-table-column |
||||||
|
type="selection" |
||||||
|
width="55"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column |
||||||
|
align="center" |
||||||
|
fixed |
||||||
|
label="姓名" |
||||||
|
prop="receiver_name" |
||||||
|
width="100"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column |
||||||
|
align="center" |
||||||
|
label="邮箱" |
||||||
|
prop="email" |
||||||
|
width="200"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column |
||||||
|
align="center" |
||||||
|
label="微信" |
||||||
|
prop="domain_name" |
||||||
|
width="260"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
<el-popover v-if="scope.row.weixin.openid" placement="top" trigger="hover"> |
||||||
|
<div style="float: right;margin-top: 10px"> |
||||||
|
<el-image :src="scope.row.weixin.head_img_url" style="width: 80px;height: 80px"/> |
||||||
|
</div> |
||||||
|
<p>昵称: {{ scope.row.weixin.nickname }}</p> |
||||||
|
<p>性别: {{ scope.row.weixin.sex|sex_filter }}</p> |
||||||
|
<p>住址: {{ scope.row.weixin.address }}</p> |
||||||
|
<p>微信ID: {{ scope.row.weixin.openid }}</p> |
||||||
|
<div slot="reference" class="name-wrapper"> |
||||||
|
<el-tag>{{ scope.row.weixin.openid }}</el-tag> |
||||||
|
</div> |
||||||
|
</el-popover> |
||||||
|
<el-tag v-else> /</el-tag> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
|
||||||
|
<el-table-column |
||||||
|
align="center" |
||||||
|
label="备注" |
||||||
|
prop="description"> |
||||||
|
</el-table-column> |
||||||
|
|
||||||
|
</el-table> |
||||||
|
<div style="text-align: left;margin-bottom: 10px;margin-top: 10px"> |
||||||
|
<el-button plain size="small" type="primary" @click="addRecevier"> |
||||||
|
新增消息接收人 |
||||||
|
</el-button> |
||||||
|
</div> |
||||||
|
<span slot="footer"> |
||||||
|
<el-button @click="updateConfig(undefined)">保存</el-button> |
||||||
|
<el-button @click="dialogChangeReceiverVisible=false">取消</el-button> |
||||||
|
</span> |
||||||
|
|
||||||
|
</el-dialog> |
||||||
|
|
||||||
|
|
||||||
|
<el-tabs v-model="activeName" tab-position="top" type="border-card" @tab-click="handleClick"> |
||||||
|
|
||||||
|
<el-tab-pane label="基本接收管理" name="config"> |
||||||
|
|
||||||
|
<el-table |
||||||
|
:data="[{name:'消息类型',email:'邮件通知',weixin:'微信通知',user:'消息接收人'}]" |
||||||
|
:show-header="false" |
||||||
|
border |
||||||
|
stripe |
||||||
|
style="width: 100%"> |
||||||
|
<el-table-column |
||||||
|
align="center" |
||||||
|
prop="name" |
||||||
|
width="200"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column |
||||||
|
align="center" |
||||||
|
prop="email" |
||||||
|
width="200"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column |
||||||
|
align="center" |
||||||
|
prop="weixin" |
||||||
|
width="200"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column |
||||||
|
align="center" |
||||||
|
prop="user"> |
||||||
|
</el-table-column> |
||||||
|
</el-table> |
||||||
|
|
||||||
|
<el-collapse v-model="activeConfig"> |
||||||
|
<el-collapse-item v-for="info in message_type_choices" :key="info.id" :disabled="info.disabled" |
||||||
|
:name="info.id"> |
||||||
|
<template slot="title"> |
||||||
|
<div style="width: 200px"> |
||||||
|
<h2>{{ info.name }}</h2> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
<el-table |
||||||
|
:data="info.data" |
||||||
|
:show-header="false" |
||||||
|
border |
||||||
|
stripe |
||||||
|
style="width: 100%"> |
||||||
|
<el-table-column |
||||||
|
align="center" |
||||||
|
fixed |
||||||
|
prop="config_name" |
||||||
|
width="200"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column |
||||||
|
align="center" |
||||||
|
fixed |
||||||
|
prop="enable_email" |
||||||
|
width="200"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
<el-checkbox v-model="scope.row.enable_email" @change="updateConfig(scope.row)">邮件</el-checkbox> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
|
||||||
|
<el-table-column |
||||||
|
align="center" |
||||||
|
fixed |
||||||
|
prop="enable_weixin" |
||||||
|
width="200"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
<el-checkbox v-model="scope.row.enable_weixin" @change="updateConfig(scope.row)">微信</el-checkbox> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
|
||||||
|
<el-table-column |
||||||
|
align="center" |
||||||
|
fixed |
||||||
|
prop="senders"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
<el-tag v-for="user in scope.row.senders" :key="user.id" style="margin-right: 3px" type="info"> |
||||||
|
{{ user.receiver_name }} |
||||||
|
</el-tag> |
||||||
|
<el-tag type="success"> |
||||||
|
<el-link :underline="false" type="success" @click="changeNotifyConfig(scope.row)">修改</el-link> |
||||||
|
</el-tag> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
|
||||||
|
</el-table> |
||||||
|
</el-collapse-item> |
||||||
|
</el-collapse> |
||||||
|
</el-tab-pane> |
||||||
|
<el-tab-pane label="消息接收人管理" name="receiver"> |
||||||
|
|
||||||
|
<div style="float: right;margin-bottom: 10px"> |
||||||
|
|
||||||
|
<el-button plain type="primary" @click="addRecevier"> |
||||||
|
新增消息接收人 |
||||||
|
</el-button> |
||||||
|
|
||||||
|
</div> |
||||||
|
<el-table |
||||||
|
v-loading="loading" |
||||||
|
:data="receiver_info_lists" |
||||||
|
border |
||||||
|
stripe |
||||||
|
style="width: 100%"> |
||||||
|
|
||||||
|
<el-table-column |
||||||
|
align="center" |
||||||
|
fixed |
||||||
|
label="姓名" |
||||||
|
prop="receiver_name" |
||||||
|
width="100"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column |
||||||
|
align="center" |
||||||
|
label="邮箱" |
||||||
|
prop="email" |
||||||
|
width="200"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column |
||||||
|
align="center" |
||||||
|
label="微信" |
||||||
|
prop="domain_name"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
<el-popover v-if="scope.row.weixin.openid" placement="top" trigger="hover"> |
||||||
|
<div style="float: right;margin-top: 10px"> |
||||||
|
<el-image :src="scope.row.weixin.head_img_url" style="width: 80px;height: 80px"/> |
||||||
|
</div> |
||||||
|
<p>昵称: {{ scope.row.weixin.nickname }}</p> |
||||||
|
<p>性别: {{ scope.row.weixin.sex|sex_filter }}</p> |
||||||
|
<p>住址: {{ scope.row.weixin.address }}</p> |
||||||
|
<p>微信ID: {{ scope.row.weixin.openid }}</p> |
||||||
|
<div slot="reference" class="name-wrapper"> |
||||||
|
<el-tag>{{ scope.row.weixin.openid }}</el-tag> |
||||||
|
</div> |
||||||
|
</el-popover> |
||||||
|
<el-tag v-else> /</el-tag> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
|
||||||
|
|
||||||
|
<el-table-column |
||||||
|
:formatter="formatter" |
||||||
|
align="center" |
||||||
|
label="添加时间" |
||||||
|
prop="create_time" |
||||||
|
width="170"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column |
||||||
|
align="center" |
||||||
|
label="备注" |
||||||
|
prop="description"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column |
||||||
|
align="center" |
||||||
|
label="操作" |
||||||
|
width="120"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
<!-- <el-button size="small" type="text" @click="editReceiver(scope.row)">编辑</el-button>--> |
||||||
|
<el-button size="small" type="text" @click="deleteReceiver(scope.row)">删除</el-button> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
</el-table> |
||||||
|
</el-tab-pane> |
||||||
|
|
||||||
|
<el-tab-pane label="阈值设置" name="threshold" style="text-align: center"> |
||||||
|
<el-tag style="margin: 20px 0"> 低于阈值设置,将会出发报警,若您配置了消息接收,将会将报警信息推送至关联的接收人</el-tag> |
||||||
|
<div style="margin: auto;width: 700px;height: 100%"> |
||||||
|
<el-form ref="form" :model="threshold" label-width="180px"> |
||||||
|
<el-form-item label="下载次数不足阈值设置"> |
||||||
|
<el-input-number v-model="threshold.notify_available_downloads" :min="0" |
||||||
|
style="width: 300px;margin: 0 20px"></el-input-number> |
||||||
|
<el-button @click="notifyThreshold('update')">保存修改</el-button> |
||||||
|
</el-form-item> |
||||||
|
|
||||||
|
<el-form-item label="签名次数不足阈值设置"> |
||||||
|
<el-input-number v-model="threshold.notify_available_signs" :min="0" |
||||||
|
style="width: 300px;margin: 0 20px"></el-input-number> |
||||||
|
<el-button @click="notifyThreshold('update')">保存修改</el-button> |
||||||
|
</el-form-item> |
||||||
|
</el-form> |
||||||
|
</div> |
||||||
|
|
||||||
|
</el-tab-pane> |
||||||
|
</el-tabs> |
||||||
|
|
||||||
|
</el-main> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import {notifyConfigInfo, NotifyInfoFun, notifyReceiverInfo, wxBindFun, wxLoginFun} from "@/restful"; |
||||||
|
import {geetest, getUserInfoFun} from "@/utils"; |
||||||
|
import {checkEmail, checkphone, format_time, getRandomStr} from "@/utils/base/utils"; |
||||||
|
|
||||||
|
export default { |
||||||
|
name: "FirUserNotify", |
||||||
|
data() { |
||||||
|
return { |
||||||
|
dialogReceiverVisible: false, |
||||||
|
captcha: {"captcha_image": '', "captcha_key": '', "length": 8}, |
||||||
|
change_type: {email: false, sms: false}, |
||||||
|
wx_visible: false, |
||||||
|
wx_login_qr_url: '', |
||||||
|
unique_key: '', |
||||||
|
userinfo: {}, |
||||||
|
addreceiverinfo: {description: '', wxopenid: '', email: '', receiver_name: '', verify_code: '', seicode: ''}, |
||||||
|
message_type_choices: [], |
||||||
|
activeConfig: [], |
||||||
|
dialogChangeReceiverVisible: false, |
||||||
|
notifyConfigSelection: [], |
||||||
|
notifyConfigMsg: {}, |
||||||
|
title: '', |
||||||
|
isedit: false, |
||||||
|
activeName: 'config', |
||||||
|
receiver_info_lists: [], |
||||||
|
loading: false, |
||||||
|
threshold: {} |
||||||
|
} |
||||||
|
}, methods: { |
||||||
|
onGetCode() { |
||||||
|
this.addreceiverinfo.auth_token = ''; |
||||||
|
this.addreceiverinfo.seicode = ''; |
||||||
|
this.onSubmit(); |
||||||
|
}, |
||||||
|
onSubmit() { |
||||||
|
let email = this.addreceiverinfo.email; |
||||||
|
let verify_code = this.addreceiverinfo.verify_code; |
||||||
|
let captcha_flag = this.addreceiverinfo.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.addreceiverinfo.email); |
||||||
|
let checkp = checkphone(this.addreceiverinfo.email); |
||||||
|
if (checke || checkp) { |
||||||
|
let params = { |
||||||
|
"target": email, |
||||||
|
"verify_code": verify_code, |
||||||
|
"captcha_key": this.captcha.captcha_key, |
||||||
|
"n_type": 'notify', |
||||||
|
}; |
||||||
|
let seicode = this.addreceiverinfo.seicode; |
||||||
|
let auth_token = this.addreceiverinfo.auth_token; |
||||||
|
if (seicode && seicode.length > 3) { |
||||||
|
params['seicode'] = seicode |
||||||
|
} |
||||||
|
if (auth_token && auth_token.length > 3) { |
||||||
|
params['auth_token'] = auth_token |
||||||
|
} |
||||||
|
if (this.auth_rules.geetest) { |
||||||
|
geetest(this, this.addreceiverinfo.email, params, (n_params) => { |
||||||
|
this.do_notify_sender(n_params) |
||||||
|
}, NotifyInfoFun) |
||||||
|
} else { |
||||||
|
this.do_notify_sender(params) |
||||||
|
} |
||||||
|
} else { |
||||||
|
this.$message({ |
||||||
|
message: '邮箱或手机号输入有误', |
||||||
|
type: 'error' |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
} else { |
||||||
|
this.$message({ |
||||||
|
message: '验证码有误', |
||||||
|
type: 'warning' |
||||||
|
}); |
||||||
|
} |
||||||
|
}, |
||||||
|
do_notify_sender(params) { |
||||||
|
NotifyInfoFun(data => { |
||||||
|
if (data.code === 1000) { |
||||||
|
this.$message.success("验证码发送成功") |
||||||
|
this.addreceiverinfo.auth_token = data.data.auth_token; |
||||||
|
} else { |
||||||
|
this.$message.error(data.msg) |
||||||
|
|
||||||
|
} |
||||||
|
}, { |
||||||
|
'methods': 'POST', |
||||||
|
'data': params |
||||||
|
}) |
||||||
|
}, |
||||||
|
|
||||||
|
get_auth_code() { |
||||||
|
NotifyInfoFun(data => { |
||||||
|
if (data.code === 1000) { |
||||||
|
this.auth_rules = data.data.auth_rules; |
||||||
|
this.captcha = this.auth_rules.captcha; |
||||||
|
this.change_type = data.data.change_type; |
||||||
|
this.addreceiverinfo.captcha_key = this.captcha.captcha_key; |
||||||
|
if (this.addreceiverinfo.verify_code) { |
||||||
|
this.addreceiverinfo.verify_code = ''; |
||||||
|
} |
||||||
|
} else { |
||||||
|
this.$message({ |
||||||
|
message: data.msg, |
||||||
|
type: 'error' |
||||||
|
}); |
||||||
|
} |
||||||
|
}, { |
||||||
|
"methods": "GET", |
||||||
|
"data": {} |
||||||
|
}); |
||||||
|
}, |
||||||
|
addRecevier() { |
||||||
|
this.addreceiverinfo = {description: '', wxopenid: '', email: '', receiver_name: '', verify_code: '', seicode: ''} |
||||||
|
this.dialogReceiverVisible = true |
||||||
|
this.title = '新增消息接收人' |
||||||
|
this.get_auth_code() |
||||||
|
}, |
||||||
|
editReceiver(receiver) { |
||||||
|
this.title = '编辑 ' + receiver.receiver_name + ' 消息接收人' |
||||||
|
this.isedit = true |
||||||
|
this.addreceiverinfo = receiver |
||||||
|
this.dialogReceiverVisible = true |
||||||
|
}, |
||||||
|
updateConfig(config = undefined) { |
||||||
|
let data = {} |
||||||
|
if (config) { |
||||||
|
data = { |
||||||
|
'config': config.id, |
||||||
|
'enable_email': config.enable_email, |
||||||
|
'enable_weixin': config.enable_weixin, |
||||||
|
'm_type': config.message_type |
||||||
|
} |
||||||
|
} else { |
||||||
|
let receiver_ids = [] |
||||||
|
for (let receiver of this.notifyConfigSelection) { |
||||||
|
receiver_ids.push(receiver.id) |
||||||
|
} |
||||||
|
data = {'config': this.notifyConfigMsg.id, 'receiver': receiver_ids, 'm_type': this.notifyConfigMsg.m_type} |
||||||
|
} |
||||||
|
|
||||||
|
notifyConfigInfo(data => { |
||||||
|
if (data.code === 1000) { |
||||||
|
this.$message.success('保存成功') |
||||||
|
if (!config) { |
||||||
|
this.dialogChangeReceiverVisible = false; |
||||||
|
} |
||||||
|
this.notifyConfigInfoFun(); |
||||||
|
} else { |
||||||
|
this.$message.error('保存失败,' + data.msg); |
||||||
|
} |
||||||
|
}, {"methods": 'PUT', "data": data}); |
||||||
|
}, |
||||||
|
changeNotifyConfig(info) { |
||||||
|
let params = {"config": info.id, "message_type": info.m_type} |
||||||
|
this.dialogChangeReceiverVisible = true; |
||||||
|
notifyReceiverInfo(data => { |
||||||
|
if (data.code === 1000) { |
||||||
|
this.receiver_info_lists = data.data; |
||||||
|
this.notifyConfigMsg = data.config |
||||||
|
// eslint-disable-next-line no-unused-vars |
||||||
|
this.$nextTick(res => { |
||||||
|
data.data.forEach(row => { |
||||||
|
for (let sender of data.senders) { |
||||||
|
if (sender.sender === row.id) { |
||||||
|
this.$refs.multipleTable.toggleRowSelection(row); |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
}) |
||||||
|
} else { |
||||||
|
this.$message.error('获取失败,' + data); |
||||||
|
} |
||||||
|
this.loading = false; |
||||||
|
}, {"methods": 'GET', "data": params}); |
||||||
|
|
||||||
|
}, |
||||||
|
handleSelectionChange(val) { |
||||||
|
this.notifyConfigSelection = val; |
||||||
|
}, |
||||||
|
// eslint-disable-next-line no-unused-vars |
||||||
|
handleClick(tab, event) { |
||||||
|
this.get_data_from_tabname(tab.name); |
||||||
|
}, |
||||||
|
cancelReceiver() { |
||||||
|
this.dialogReceiverVisible = false; |
||||||
|
this.addreceiverinfo = {description: '', wxopenid: '', email: '', receiver_name: '', verify_code: '', seicode: ''} |
||||||
|
}, |
||||||
|
saveReceiver() { |
||||||
|
notifyReceiverInfo(data => { |
||||||
|
if (data.code === 1000) { |
||||||
|
this.$message.success('操作成功'); |
||||||
|
this.dialogReceiverVisible = false; |
||||||
|
if (this.dialogChangeReceiverVisible) { |
||||||
|
this.changeNotifyConfig(this.notifyConfigMsg) |
||||||
|
} else { |
||||||
|
this.get_data_from_tabname(this.activeName); |
||||||
|
} |
||||||
|
} else { |
||||||
|
this.$message.error('操作失败,' + data.msg); |
||||||
|
} |
||||||
|
}, {"methods": 'POST', 'data': this.addreceiverinfo}); |
||||||
|
}, |
||||||
|
deleteReceiver(sinfo) { |
||||||
|
|
||||||
|
this.$confirm(`将要删除接收人 ${sinfo.receiver_name}, 是否继续?`, '警告', { |
||||||
|
confirmButtonText: '确定', |
||||||
|
cancelButtonText: '取消', |
||||||
|
type: 'warning' |
||||||
|
}).then(() => { |
||||||
|
notifyReceiverInfo(data => { |
||||||
|
if (data.code === 1000) { |
||||||
|
this.$message.success('删除成功'); |
||||||
|
this.notifyReceiverInfoFun(); |
||||||
|
} |
||||||
|
}, {"methods": 'DELETE', 'data': {'id': sinfo.id}}) |
||||||
|
}).catch(() => { |
||||||
|
this.$message({ |
||||||
|
type: 'info', |
||||||
|
message: '已取消删除' |
||||||
|
}); |
||||||
|
}); |
||||||
|
|
||||||
|
}, |
||||||
|
|
||||||
|
notifyReceiverInfoFun() { |
||||||
|
this.loading = true; |
||||||
|
notifyReceiverInfo(data => { |
||||||
|
if (data.code === 1000) { |
||||||
|
this.receiver_info_lists = data.data; |
||||||
|
} else { |
||||||
|
this.$message.error('获取失败,' + data); |
||||||
|
} |
||||||
|
this.loading = false; |
||||||
|
}, {"methods": 'GET'}); |
||||||
|
}, |
||||||
|
setActiveConfig(message_type_choices) { |
||||||
|
let activeConfig = [] |
||||||
|
for (let i of message_type_choices) { |
||||||
|
activeConfig.push(i.id) |
||||||
|
} |
||||||
|
this.activeConfig = activeConfig; |
||||||
|
}, |
||||||
|
notifyConfigInfoFun() { |
||||||
|
this.loading = true; |
||||||
|
notifyConfigInfo(data => { |
||||||
|
if (data.code === 1000) { |
||||||
|
this.receiver_info_lists = data.data; |
||||||
|
this.message_type_choices = data.message_type_choices; |
||||||
|
this.setActiveConfig(this.message_type_choices); |
||||||
|
} else { |
||||||
|
this.$message.error('获取失败,' + data); |
||||||
|
} |
||||||
|
this.loading = false; |
||||||
|
}, {"methods": 'GET'}); |
||||||
|
}, |
||||||
|
notifyThreshold(act) { |
||||||
|
notifyConfigInfo(data => { |
||||||
|
if (data.code === 1000) { |
||||||
|
this.threshold = data.data |
||||||
|
if (act !== 'get') { |
||||||
|
this.$message.success('保存成功') |
||||||
|
} |
||||||
|
} else { |
||||||
|
this.$message.error('获取失败,' + data); |
||||||
|
} |
||||||
|
this.loading = false; |
||||||
|
}, {"methods": 'POST', 'data': {'act': act, 'threshold': this.threshold}}); |
||||||
|
}, |
||||||
|
|
||||||
|
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) { |
||||||
|
if (this.userinfo.uid === data.data.uid) { |
||||||
|
if (data.data.to_user) { |
||||||
|
this.addreceiverinfo.wxopenid = data.data.to_user |
||||||
|
} |
||||||
|
this.$message.success("绑定成功"); |
||||||
|
this.wx_visible = false; |
||||||
|
} |
||||||
|
} else if (data.code === 1005) { |
||||||
|
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) |
||||||
|
} |
||||||
|
}, { |
||||||
|
"methods": "POST", |
||||||
|
data: {"ticket": wx_login_ticket, "unique_key": unique_key} |
||||||
|
}) |
||||||
|
}, |
||||||
|
wxLogin() { |
||||||
|
this.wx_visible = !this.wx_visible; |
||||||
|
this.wx_login_qr_url = ''; |
||||||
|
if (this.wx_visible) { |
||||||
|
wxBindFun(data => { |
||||||
|
if (data.code === 1000) { |
||||||
|
this.wx_login_qr_url = data.data.qr; |
||||||
|
this.loop_get_wx_info(data.data.ticket); |
||||||
|
} else { |
||||||
|
this.$message.error(data.msg); |
||||||
|
this.wx_visible = false; |
||||||
|
} |
||||||
|
}, { |
||||||
|
"methods": "POST", "data": {"unique_key": this.unique_key, "w_type": 'notify'} |
||||||
|
}) |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
// eslint-disable-next-line no-unused-vars |
||||||
|
formatter(row, column) { |
||||||
|
return format_time(row.create_time) |
||||||
|
}, |
||||||
|
// eslint-disable-next-line no-unused-vars |
||||||
|
get_data_from_tabname(tabname, data = {}) { |
||||||
|
this.$router.push({"name": 'FirUserNotify', params: {act: tabname}}); |
||||||
|
if (tabname === "config") { |
||||||
|
this.notifyConfigInfoFun(); |
||||||
|
} else if (tabname === "receiver") { |
||||||
|
this.notifyReceiverInfoFun(); |
||||||
|
} else if (tabname === "threshold") { |
||||||
|
this.notifyThreshold('get'); |
||||||
|
} |
||||||
|
}, |
||||||
|
}, mounted() { |
||||||
|
getUserInfoFun(this); |
||||||
|
this.userinfo = this.$store.state.userinfo; |
||||||
|
this.unique_key = getRandomStr(); |
||||||
|
if (this.$route.params.act) { |
||||||
|
let activeName = this.$route.params.act; |
||||||
|
let activeName_list = ["config", "receiver", "threshold"]; |
||||||
|
for (let index in activeName_list) { |
||||||
|
if (activeName_list[index] === activeName) { |
||||||
|
this.activeName = activeName; |
||||||
|
this.get_data_from_tabname(activeName); |
||||||
|
return |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
this.get_data_from_tabname(this.activeName); |
||||||
|
}, filters: { |
||||||
|
sex_filter: function (x) { |
||||||
|
let ret = '未知'; |
||||||
|
if (x === 1) { |
||||||
|
ret = '男' |
||||||
|
} else if (x === 2) { |
||||||
|
ret = '女' |
||||||
|
} |
||||||
|
return ret; |
||||||
|
}, |
||||||
|
}, watch: { |
||||||
|
'$store.state.userinfo': function () { |
||||||
|
this.userinfo = this.$store.state.userinfo; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
</script> |
||||||
|
|
||||||
|
<style scoped> |
||||||
|
.el-main { |
||||||
|
text-align: center; |
||||||
|
margin: 20px auto 100px; |
||||||
|
width: 1166px; |
||||||
|
position: relative; |
||||||
|
padding-bottom: 1px; |
||||||
|
color: #9b9b9b; |
||||||
|
-webkit-font-smoothing: antialiased; |
||||||
|
border-radius: 1%; |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,317 @@ |
|||||||
|
<template> |
||||||
|
<el-main> |
||||||
|
|
||||||
|
<el-row style="margin-bottom: 5px"> |
||||||
|
<el-col :span="3"> |
||||||
|
<el-radio-group v-model="searchfromtype"> |
||||||
|
<el-radio-button icon="el-icon-mobile-phone" label="android"><i |
||||||
|
class="iconfont icon-android2"/> |
||||||
|
</el-radio-button> |
||||||
|
<el-radio-button label="ios"><i class="iconfont icon-ios"/> |
||||||
|
</el-radio-button> |
||||||
|
</el-radio-group> |
||||||
|
|
||||||
|
</el-col> |
||||||
|
<el-col :span="8"> |
||||||
|
<el-row> |
||||||
|
<el-col :span="18"> |
||||||
|
<el-input |
||||||
|
v-model="keysearch" |
||||||
|
clearable |
||||||
|
placeholder="请输入名称搜索" |
||||||
|
@click="searchapps" |
||||||
|
@keyup.enter.native="searchapps"> |
||||||
|
</el-input> |
||||||
|
</el-col> |
||||||
|
<el-col :span="6"> |
||||||
|
|
||||||
|
<el-button icon="el-icon-search" @click="searchFun"> |
||||||
|
</el-button> |
||||||
|
</el-col> |
||||||
|
</el-row> |
||||||
|
</el-col> |
||||||
|
|
||||||
|
<el-col :offset="5" :span="8"> |
||||||
|
<el-row> |
||||||
|
<el-col :span="8"> |
||||||
|
<el-checkbox v-model="checkAll" :indeterminate="isIndeterminate" style="margin-top: 10px" |
||||||
|
@change="handleCheckAllChange">当前页全选【{{ checkedQrcodes.length }}】 |
||||||
|
</el-checkbox> |
||||||
|
</el-col> |
||||||
|
<el-col :span="13" style="float: right"> |
||||||
|
<el-button @click="savemany">批量保存选中下载码到本地</el-button> |
||||||
|
</el-col> |
||||||
|
</el-row> |
||||||
|
</el-col> |
||||||
|
</el-row> |
||||||
|
|
||||||
|
<el-row id="showqr"> |
||||||
|
<el-checkbox-group v-model="checkedQrcodes" @change="handlecheckedQrcodesChange"> |
||||||
|
<el-col v-for="appinfo in qrcode_info_list" :key="appinfo.app_id" :span="5" style="margin-left: 40px"> |
||||||
|
<el-checkbox :label="appinfo.app_id" border style="height: 320px"> |
||||||
|
<el-card :body-style="{textAlign:'center',padding:'8px'}" shadow="hover"> |
||||||
|
<vue-qr :callback="qrback" |
||||||
|
:correctLevel="qrinfo.correctLevel" :logoCornerRadius="qrinfo.logoCornerRadius" |
||||||
|
:logoScale="qrinfo.logoScale" |
||||||
|
:logoSrc="appinfo.master_release.icon_url" |
||||||
|
:margin="qrinfo.margin" :qid="appinfo.app_id" |
||||||
|
:size="200" |
||||||
|
:text="appinfo.preview_url"> |
||||||
|
</vue-qr> |
||||||
|
<div style="margin: 5px 0 5px"> |
||||||
|
<i v-if="appinfo.type === 1" class=" type-icon iconfont icon-ios"/> |
||||||
|
<i v-if="appinfo.type === 0" class="type-icon iconfont icon-android2"/> |
||||||
|
|
||||||
|
<span>{{ appinfo.name }}</span> |
||||||
|
<div class="bottom clearfix"> |
||||||
|
<el-popover placement="top" trigger="hover"> |
||||||
|
<span v-clipboard:copy="appinfo.preview_url" |
||||||
|
v-clipboard:success="copy_success" |
||||||
|
>{{ appinfo.preview_url }}</span> |
||||||
|
<div slot="reference" class="name-wrapper"> |
||||||
|
<el-button plain size="small" type="primary" @click="go_download(appinfo)">预览</el-button> |
||||||
|
<el-button plain size="small" type="primary" @click="save_qr(appinfo)">保存本地</el-button> |
||||||
|
</div> |
||||||
|
</el-popover> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</el-card> |
||||||
|
</el-checkbox> |
||||||
|
</el-col> |
||||||
|
</el-checkbox-group> |
||||||
|
</el-row> |
||||||
|
|
||||||
|
</el-main> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
|
||||||
|
import {qrcodeinfo} from "@/restful"; |
||||||
|
import {getScrollHeight, getScrollTop, getUserInfoFun, getWindowHeight} from '@/utils' |
||||||
|
import VueQr from 'vue-qr'; |
||||||
|
|
||||||
|
export default { |
||||||
|
name: "FirUserQrcode", |
||||||
|
components: { |
||||||
|
VueQr |
||||||
|
}, |
||||||
|
data() { |
||||||
|
return { |
||||||
|
has_next: false, |
||||||
|
firstloadflag: true, |
||||||
|
query: {'page': 1, size: 20}, |
||||||
|
searchflag: false, |
||||||
|
keysearch: '', |
||||||
|
searchfromtype: '', |
||||||
|
loadingobj: null, |
||||||
|
checkAll: false, |
||||||
|
checkedQrcodes: [], |
||||||
|
isIndeterminate: false, |
||||||
|
allQrcodeAppid: [], |
||||||
|
qrcode_info_list: [], |
||||||
|
orgqrcode_info_list: [], |
||||||
|
qrcode_img_info: {}, |
||||||
|
qrinfo: { |
||||||
|
logoScale: 0.3, |
||||||
|
logoCornerRadius: 12, |
||||||
|
correctLevel: 3, |
||||||
|
margin: 10 |
||||||
|
}, |
||||||
|
} |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
copy_success() { |
||||||
|
this.$message.success('复制剪切板成功'); |
||||||
|
}, |
||||||
|
auto_load() { |
||||||
|
if (getScrollTop() + getWindowHeight() >= getScrollHeight()) { |
||||||
|
if (this.has_next) { //先判断下一页是否有数据 |
||||||
|
if (this.autoloadflag) { |
||||||
|
this.autoloadflag = false; |
||||||
|
if (this.qrcode_info_list.length === 0) { |
||||||
|
this.query.page = 1; |
||||||
|
} else { |
||||||
|
this.query.page += 1; |
||||||
|
} |
||||||
|
if (this.searchfromtype !== '') { |
||||||
|
this.query.type = this.searchfromtype; |
||||||
|
} |
||||||
|
this.UserQrcodeFun(this.query); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
init_value() { |
||||||
|
this.checkAll = false; |
||||||
|
this.checkedQrcodes = []; |
||||||
|
this.isIndeterminate = false; |
||||||
|
this.qrcode_info_list = []; |
||||||
|
this.orgqrcode_info_list = []; |
||||||
|
this.checkedQrcodes = []; |
||||||
|
this.allQrcodeAppid = []; |
||||||
|
this.qrcode_img_info = {}; |
||||||
|
}, |
||||||
|
searchFun() { |
||||||
|
let keysearch = this.keysearch.replace(/^\s+|\s+$/g, ""); |
||||||
|
if (keysearch === '') { |
||||||
|
this.searchflag = false; |
||||||
|
this.init_value(); |
||||||
|
this.query.page = 1; |
||||||
|
if (this.searchfromtype) { |
||||||
|
this.UserQrcodeFun({"type": this.searchfromtype}); |
||||||
|
} else { |
||||||
|
this.UserQrcodeFun({}); |
||||||
|
} |
||||||
|
} else { |
||||||
|
this.searchflag = true |
||||||
|
} |
||||||
|
if (this.searchflag) { |
||||||
|
this.qrcode_info_list = []; |
||||||
|
this.orgqrcode_info_list = []; |
||||||
|
if (this.searchfromtype) { |
||||||
|
this.UserQrcodeFun({"type": this.searchfromtype, 'page': 1, size: 999}); |
||||||
|
} else { |
||||||
|
this.UserQrcodeFun({'page': 1, size: 999}); |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
searchapps() { |
||||||
|
let keysearch = this.keysearch.replace(/^\s+|\s+$/g, ""); |
||||||
|
let newqrcode_info_list = []; |
||||||
|
for (let i = 0; i < this.orgqrcode_info_list.length; i++) { |
||||||
|
if (this.orgqrcode_info_list[i].name.search(keysearch) >= 0) { |
||||||
|
newqrcode_info_list.push(this.orgqrcode_info_list[i]); |
||||||
|
} |
||||||
|
} |
||||||
|
if (keysearch === "") { |
||||||
|
this.qrcode_info_list = this.orgqrcode_info_list.slice(); |
||||||
|
} else { |
||||||
|
this.qrcode_info_list = newqrcode_info_list.slice(); |
||||||
|
} |
||||||
|
|
||||||
|
}, |
||||||
|
get_appinfo_from_appid(app_id) { |
||||||
|
for (let i = 0; i < this.qrcode_info_list.length; i++) { |
||||||
|
if (app_id === this.qrcode_info_list[i].app_id) { |
||||||
|
return this.qrcode_info_list[i]; |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
savemany() { |
||||||
|
for (let i = 0; i < this.checkedQrcodes.length; i++) { |
||||||
|
this.save_qr(this.get_appinfo_from_appid(this.allQrcodeAppid[i])) |
||||||
|
} |
||||||
|
}, |
||||||
|
handleCheckAllChange(val) { |
||||||
|
this.checkedQrcodes = val ? this.allQrcodeAppid : []; |
||||||
|
this.isIndeterminate = false; |
||||||
|
}, |
||||||
|
handlecheckedQrcodesChange(value) { |
||||||
|
let checkedCount = value.length; |
||||||
|
this.checkAll = checkedCount === this.allQrcodeAppid.length; |
||||||
|
this.isIndeterminate = checkedCount > 0 && checkedCount < this.allQrcodeAppid.length; |
||||||
|
}, |
||||||
|
go_download(appinfo) { |
||||||
|
window.open(appinfo.preview_url, '_blank', ''); |
||||||
|
}, |
||||||
|
qrback(dataUrl, id) { |
||||||
|
this.qrcode_img_info[id] = dataUrl; |
||||||
|
this.allQrcodeAppid.push(id); |
||||||
|
}, |
||||||
|
save_qr(appinfo) { |
||||||
|
let dtype = "I"; |
||||||
|
if (appinfo.master_release.release_type === 0) { |
||||||
|
dtype = "A"; |
||||||
|
} |
||||||
|
let a = document.createElement('a'); |
||||||
|
// 下载图名字 |
||||||
|
a.download = appinfo.name + '_' + dtype + "_下载码"; |
||||||
|
a.href = this.qrcode_img_info[appinfo.app_id]; |
||||||
|
//合成函数,执行下载 |
||||||
|
a.dispatchEvent(new MouseEvent('click')) |
||||||
|
}, |
||||||
|
UserQrcodeFun(params) { |
||||||
|
this.loadingobj = this.$loading({ |
||||||
|
lock: true, |
||||||
|
text: '加载中', |
||||||
|
spinner: 'el-icon-loading', |
||||||
|
// background: 'rgba(0, 0, 0, 0.7)' |
||||||
|
}); |
||||||
|
qrcodeinfo(data => { |
||||||
|
if (data.code === 1000) { |
||||||
|
if (this.firstloadflag) { |
||||||
|
window.addEventListener('scroll', this.auto_load); |
||||||
|
this.firstloadflag = false |
||||||
|
} |
||||||
|
this.autoloadflag = true; |
||||||
|
this.qrcode_info_list = this.qrcode_info_list.concat(data.data); |
||||||
|
this.has_next = data.has_next; |
||||||
|
this.orgqrcode_info_list = this.qrcode_info_list.slice(); //深拷贝 |
||||||
|
this.hdata = data.hdata; |
||||||
|
this.searchapps(); |
||||||
|
|
||||||
|
} else { |
||||||
|
this.$message.error("信息获取失败") |
||||||
|
} |
||||||
|
this.loadingobj.close(); |
||||||
|
}, {methods: 'GET', data: params}) |
||||||
|
}, |
||||||
|
|
||||||
|
|
||||||
|
}, mounted() { |
||||||
|
getUserInfoFun(this); |
||||||
|
this.UserQrcodeFun() |
||||||
|
}, |
||||||
|
watch: { |
||||||
|
|
||||||
|
// eslint-disable-next-line no-unused-vars |
||||||
|
keysearch: function (val, oldVal) { |
||||||
|
// this.searchapps() |
||||||
|
let keysearch = this.keysearch.replace(/^\s+|\s+$/g, ""); |
||||||
|
if (keysearch === "") { |
||||||
|
this.searchFun() |
||||||
|
} |
||||||
|
}, |
||||||
|
// eslint-disable-next-line no-unused-vars |
||||||
|
searchfromtype: function (val, oldVal) { |
||||||
|
this.qrcode_info_list = []; |
||||||
|
this.query.page = 1; |
||||||
|
// this.keysearch=''; |
||||||
|
this.searchFun(); |
||||||
|
// this.getappsFun({"type": this.searchfromtype}); |
||||||
|
}, |
||||||
|
} |
||||||
|
} |
||||||
|
</script> |
||||||
|
|
||||||
|
<style scoped> |
||||||
|
.el-main { |
||||||
|
margin: 20px auto 100px; |
||||||
|
width: 1166px; |
||||||
|
position: relative; |
||||||
|
padding-bottom: 1px; |
||||||
|
color: #9b9b9b; |
||||||
|
-webkit-font-smoothing: antialiased; |
||||||
|
border-radius: 1%; |
||||||
|
} |
||||||
|
|
||||||
|
.bottom { |
||||||
|
margin-top: 10px; |
||||||
|
} |
||||||
|
|
||||||
|
.clearfix:before, |
||||||
|
.clearfix:after { |
||||||
|
display: table; |
||||||
|
content: ""; |
||||||
|
} |
||||||
|
|
||||||
|
.clearfix:after { |
||||||
|
clear: both |
||||||
|
} |
||||||
|
|
||||||
|
#showqr /deep/ .el-checkbox__input { |
||||||
|
display: none; |
||||||
|
} |
||||||
|
|
||||||
|
</style> |