├── .github
└── workflows
│ └── deploy.yml
├── .gitignore
├── Dockerfile
├── README.md
├── conf.d
├── admin.clicli.cc.conf
├── admin.clicli.cc.key
├── admin.clicli.cc.pem
├── api.clicli.cc.conf
├── api.clicli.cc.key
├── api.clicli.cc.pem
├── www.clicli.cc.conf
├── www.clicli.cc.key
└── www.clicli.cc.pem
├── package.json
├── packages
├── fre
│ ├── .babelrc
│ ├── .gitignore
│ ├── LICENSE
│ ├── README.md
│ ├── dist
│ │ ├── index.html
│ │ ├── main.css
│ │ ├── main.js
│ │ └── vendors~main.js
│ ├── docs
│ │ ├── 404.html
│ │ └── index.html
│ ├── package.json
│ ├── src
│ │ ├── api
│ │ │ └── get.js
│ │ ├── component
│ │ │ ├── comment-list
│ │ │ │ └── index.js
│ │ │ ├── footer
│ │ │ │ ├── index.js
│ │ │ │ └── index.styl
│ │ │ ├── header
│ │ │ │ ├── index.js
│ │ │ │ └── index.styl
│ │ │ ├── home
│ │ │ │ ├── index.js
│ │ │ │ ├── index.styl
│ │ │ │ └── m.styl
│ │ │ ├── page
│ │ │ │ ├── index.js
│ │ │ │ └── index.styl
│ │ │ ├── post-detail
│ │ │ │ ├── index.js
│ │ │ │ ├── index.styl
│ │ │ │ └── snarkdown.js
│ │ │ ├── post-list
│ │ │ │ ├── index.js
│ │ │ │ └── index.styl
│ │ │ ├── rank
│ │ │ │ ├── index.js
│ │ │ │ └── index.styl
│ │ │ ├── recommend
│ │ │ │ ├── index.js
│ │ │ │ └── index.styl
│ │ │ ├── search
│ │ │ │ ├── index.js
│ │ │ │ └── index.styl
│ │ │ ├── ugc-list
│ │ │ │ ├── index.js
│ │ │ │ └── index.styl
│ │ │ ├── video-list
│ │ │ │ ├── index.js
│ │ │ │ └── index.styl
│ │ │ └── week-list
│ │ │ │ ├── index.js
│ │ │ │ └── index.styl
│ │ ├── index.html
│ │ ├── index.js
│ │ ├── public
│ │ │ ├── css
│ │ │ │ └── var.styl
│ │ │ ├── img
│ │ │ │ └── sliders
│ │ │ │ │ ├── 0.jpg
│ │ │ │ │ ├── 1.jpg
│ │ │ │ │ ├── 2.jpg
│ │ │ │ │ └── 3.jpg
│ │ │ └── js
│ │ │ │ ├── const.js
│ │ │ │ ├── fetch.js
│ │ │ │ └── util.js
│ │ ├── use-location.js
│ │ └── widget
│ │ │ ├── ad
│ │ │ └── index.js
│ │ │ ├── eplayer
│ │ │ ├── index.js
│ │ │ └── index.styl
│ │ │ ├── search
│ │ │ ├── index.js
│ │ │ └── index.styl
│ │ │ ├── tab
│ │ │ ├── index.js
│ │ │ └── index.styl
│ │ │ └── tag
│ │ │ ├── index.js
│ │ │ └── index.styl
│ ├── webpack.config.js
│ └── yarn.lock
└── react
│ ├── .babelrc
│ ├── .gitignore
│ ├── README.md
│ ├── dist
│ ├── index.html
│ ├── main.css
│ ├── main.js
│ ├── runtime~main.js
│ └── vendors~main.js
│ ├── package-lock.json
│ ├── package.json
│ ├── src
│ ├── api
│ │ ├── comment.js
│ │ ├── jx.js
│ │ ├── post.js
│ │ ├── user.js
│ │ └── video.js
│ ├── app.js
│ ├── base
│ │ ├── confirm
│ │ │ ├── confirm.css
│ │ │ └── confirm.js
│ │ ├── list-view
│ │ │ ├── list-view.js
│ │ │ └── listview.css
│ │ ├── loading
│ │ │ ├── loading.css
│ │ │ ├── loading.gif
│ │ │ └── loading.js
│ │ ├── markdown
│ │ │ ├── markdown.css
│ │ │ └── markdown.js
│ │ ├── reach-box
│ │ │ ├── reach-box.css
│ │ │ └── reach-box.js
│ │ └── top-tip
│ │ │ ├── top-tip.css
│ │ │ └── top-tip.js
│ ├── common
│ │ ├── js
│ │ │ ├── axios.js
│ │ │ └── util.js
│ │ └── style
│ │ │ ├── iconfont.css
│ │ │ ├── index.css
│ │ │ └── reset.css
│ ├── component
│ │ ├── editor-user
│ │ │ ├── editor-user.css
│ │ │ └── editor-user.js
│ │ ├── editor-video
│ │ │ └── editor-video.js
│ │ ├── header
│ │ │ ├── header.css
│ │ │ └── header.js
│ │ ├── login
│ │ │ ├── login.css
│ │ │ └── login.js
│ │ ├── post-list
│ │ │ └── post-list.js
│ │ ├── register
│ │ │ └── register.js
│ │ ├── user-info
│ │ │ ├── user-info.css
│ │ │ └── user-info.js
│ │ ├── user-list
│ │ │ ├── user-list.css
│ │ │ └── user-list.js
│ │ └── write-article
│ │ │ ├── wirte-article.js
│ │ │ └── write-article.css
│ ├── hoc
│ │ ├── auth
│ │ │ └── auth.js
│ │ └── handle-form
│ │ │ └── handle-form.js
│ ├── index.html
│ ├── index.js
│ └── store
│ │ ├── actions.js
│ │ ├── index.js
│ │ ├── mutations.js
│ │ └── state.js
│ └── webpack.config.js
├── pnpm-lock.yaml
├── pnpm-workspace.yaml
└── yarn.lock
/.github/workflows/deploy.yml:
--------------------------------------------------------------------------------
1 | on:
2 | push:
3 | branches:
4 | - master
5 | jobs:
6 | publish:
7 | runs-on: ubuntu-latest
8 | steps:
9 | - uses: actions/checkout@v2
10 | - name: Build Dist
11 | run: |
12 | yarn install
13 | yarn build:fre
14 | cd ./packages/react
15 | yarn install
16 | yarn build
17 | - name: Build Image
18 | env:
19 | DockerUsername: ${{ secrets.DOCKER_USERNAME }}
20 | DockerPassword: ${{ secrets.DOCKER_PASSWORD }}
21 | run: |
22 | docker login -u $DockerUsername -p $DockerPassword
23 | docker build -t yisar/clicli_fe .
24 | docker push yisar/clicli_fe
25 | deploy:
26 | runs-on: ubuntu-latest
27 | needs: [publish]
28 | steps:
29 | - uses: appleboy/ssh-action@master
30 | with:
31 | host: ${{ secrets.DEPLOY_HOST }}
32 | username: ${{ secrets.DEPLOY_USERNAME }}
33 | password: ${{ secrets.DEPLOY_PASSWORD }}
34 | port: 22
35 | script: |
36 | docker pull yisar/clicli_fe
37 | docker-compose up -d
38 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | **/**/node_modules/
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM nginx
2 |
3 | USER root
4 |
5 | COPY /packages/react/dist/ /usr/share/nginx/html/react/
6 | COPY /packages/fre/dist/ /usr/share/nginx/html/fre/
7 |
8 | RUN chmod -R 775 /usr/share/nginx/html
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # fre-clicli
2 |
3 | c 站前端 monorepo
4 |
5 | ### run
6 |
7 | 本仓库是使用 pnpm 构建的 monorepo,可以单独打开 packages 下面的文件夹单独进行开发
--------------------------------------------------------------------------------
/conf.d/admin.clicli.cc.conf:
--------------------------------------------------------------------------------
1 | server {
2 | listen 80;
3 | server_name admin.clicli.cc;
4 | return 301 https://admin.clicli.cc;
5 | }
6 |
7 | server {
8 | listen 443 ssl;
9 | server_name admin.clicli.cc;
10 | ssl_certificate conf.d/admin.clicli.cc.pem;
11 | ssl_certificate_key conf.d/admin.clicli.cc.key;
12 | ssl_session_timeout 5m;
13 | ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
14 | ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
15 | ssl_prefer_server_ciphers on;
16 |
17 | location / {
18 | root /usr/share/nginx/html/react;
19 | index index.html;
20 | try_files $uri $uri/ /index.html;
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/conf.d/admin.clicli.cc.key:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIIEoQIBAAKCAQEAoys1Pe6aTEIeciEi0nFmg3y0k+khq+qYzGZL2ADPaaezNJWC
3 | v0TZU2FuXx0WtVr5ZbQuGrI81KeDY6o52cmDUJQnbkq+d0f7mNlBGwJYoIrMZ/eZ
4 | 768P0jt9WCrPkTONCokVyAe6H5uUCStaKgQ8gAhXLitOawC+gCILvr21MA66/y9m
5 | djYFE1H8xS7qAD7Wu96UTKwDdOomtayfLRcS5LSwlvzsOScrsw448VU8vMYnZlzW
6 | pi+jVjpn332y8yUgRpo30xneMRpLRehVUdxUW8L+iYhCGeYYi0iRUwxfMS0QnceL
7 | epHhL1BSmAdEbqxe6ae2NkiI03y/AeauUzAkOwIDAQABAoIBAAHI3ZkDAxNsDBxm
8 | psemdd76Sv9TJwsguPGDYB3JfhTc8+WfVpuNvtLEPgpl4KaBi2v3v7yLA1KDT1L6
9 | 8A1xwGRUbbOT6oFje1z9abjh50lz1MiBhmCyVkbDLJvKQnrtrwOhr2gaRyIRXlnu
10 | hdq8l4ZokPHwVB5xFteDIWqOQjnd6uCIWBk6wVMAXkrFlmNfCRyfND2bPeph8cHL
11 | CP9LOyGaDujv5gAGDAuEeW6kQQLtyeegabKNWfMgkOWsA77Y64BDU918AaKRQYXM
12 | GBt/KmfE/3JxM84lGODsiELZ8fRmtzshqVc4p/vM5JFqGDbzDBnWGyx5LKs/9tQv
13 | nYeX0AECgYEA5bI75cetZu1jDMVfIPkzRmDx6XtRfBkdfDuHXiW4T/Tfny38M0Ph
14 | /gxGXgiQ9uObPpfDW3hXq8G9Vn0tjW4HhZ7riLkgIS7/SQSYTVc2vKXiC14N9RFC
15 | YatBOvU7zV2XJs+w+feFkdOQDnPm4aqzluPFnW/zHFDqeT6U+u18Ch8CgYEAtdqo
16 | a4xfImDB53L/XviJZDEY7j4cIMdHL//c1DJud38fK8TbY0WKAs6YX4K8ZZGYnJZX
17 | 3Yx4EtZyfN7YNjZOes3Qo2IFeztb1XNOfmkxMvKpzRWIEdaaWUvPfE0G2mrGVJLp
18 | iukxKlaUtL7jzdI8Q2vzvGzH34BYYyNNqNKnGmUCgYACrmLumrcWdXzrgD5NBzum
19 | /ai1PgBEf5KNibBZ0/zjygr2M7Y27vrrWT9VB6qRhzSftWvNXIlBcwB/yvRGK1uh
20 | HqrHLMoIOSE3u/r/JB56c0FBOrbU/n+U3kfjpUsuaYJDLLd3I4GGoz6SPJ4cUj7I
21 | ax46aT0gPn2OLsHUcAM7pwJ/VIhPwa5+inxvpibOjlb5hplL/XLhoFsBvE4zWHAY
22 | 6XMuCip30K2CecuPCNa8vHnxdthr/5BMQHVuwpzT5F9aG7uQQGJQKfhtt8rhseEz
23 | /XrPc4WOurwHA3s5943WobEAgE/KP8gmEogsl9gkDIiteqmzouLuBfajH3JJpzBE
24 | fQKBgQCJjj0DhBGXemklPSGpy4d4lI+mgVNidyy9pgRcvUDP6qxvVNMk7Dc6KZLB
25 | ZEasgeqD9D5is/dLYk4avJPfTM0epIponI3fOyJ9AxHQfda/F/GewEow4pnDE9XQ
26 | gjQTIGAvNnRmwVjXQdXjgo7uX0cH1mR6g4BCyu4Ge/h/xl0zPA==
27 | -----END RSA PRIVATE KEY-----
28 |
--------------------------------------------------------------------------------
/conf.d/admin.clicli.cc.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIF8jCCBNqgAwIBAgIQBkrPlVpflfuCW+jY8kAW+jANBgkqhkiG9w0BAQsFADBu
3 | MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
4 | d3cuZGlnaWNlcnQuY29tMS0wKwYDVQQDEyRFbmNyeXB0aW9uIEV2ZXJ5d2hlcmUg
5 | RFYgVExTIENBIC0gRzEwHhcNMjExMjE5MDAwMDAwWhcNMjIxMjIwMjM1OTU5WjAa
6 | MRgwFgYDVQQDEw9hZG1pbi5jbGljbGkuY2MwggEiMA0GCSqGSIb3DQEBAQUAA4IB
7 | DwAwggEKAoIBAQCjKzU97ppMQh5yISLScWaDfLST6SGr6pjMZkvYAM9pp7M0lYK/
8 | RNlTYW5fHRa1WvlltC4asjzUp4NjqjnZyYNQlCduSr53R/uY2UEbAligisxn95nv
9 | rw/SO31YKs+RM40KiRXIB7ofm5QJK1oqBDyACFcuK05rAL6AIgu+vbUwDrr/L2Z2
10 | NgUTUfzFLuoAPta73pRMrAN06ia1rJ8tFxLktLCW/Ow5JyuzDjjxVTy8xidmXNam
11 | L6NWOmfffbLzJSBGmjfTGd4xGktF6FVR3FRbwv6JiEIZ5hiLSJFTDF8xLRCdx4t6
12 | keEvUFKYB0RurF7pp7Y2SIjTfL8B5q5TMCQ7AgMBAAGjggLeMIIC2jAfBgNVHSME
13 | GDAWgBRVdE+yck/1YLpQ0dfmUVyaAYca1zAdBgNVHQ4EFgQUUnDHfTKBYgvEX0VB
14 | XUVt/rzUv9UwGgYDVR0RBBMwEYIPYWRtaW4uY2xpY2xpLmNjMA4GA1UdDwEB/wQE
15 | AwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwPgYDVR0gBDcwNTAz
16 | BgZngQwBAgEwKTAnBggrBgEFBQcCARYbaHR0cDovL3d3dy5kaWdpY2VydC5jb20v
17 | Q1BTMIGABggrBgEFBQcBAQR0MHIwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRp
18 | Z2ljZXJ0LmNvbTBKBggrBgEFBQcwAoY+aHR0cDovL2NhY2VydHMuZGlnaWNlcnQu
19 | Y29tL0VuY3J5cHRpb25FdmVyeXdoZXJlRFZUTFNDQS1HMS5jcnQwCQYDVR0TBAIw
20 | ADCCAX0GCisGAQQB1nkCBAIEggFtBIIBaQFnAHUARqVV63X6kSAwtaKJafTzfREs
21 | QXS+/Um4havy/HD+bUcAAAF90P8s2gAABAMARjBEAiAEoBOrHJRiAHzuIdlWuN1E
22 | 6/Cqe+rmqynuqFfFAKVYjwIgCmcKu5odDk0KzJINT3NTCAnXvzRQV8ewgd/Ph9j/
23 | bPoAdQBRo7D1/QF5nFZtuDd4jwykeswbJ8v3nohCmg3+1IsF5QAAAX3Q/y0PAAAE
24 | AwBGMEQCIEPEkdhcK2Y69VirtdNiW0azE124ENdxd8G3QHa2f1vYAiAkiq7hexzS
25 | qWPokT6vMlnGqz2Jn73tMDGvao2nySHvVgB3AEHIyrHfIkZKEMahOglCh15OMYsb
26 | A+vrS8do8JBilgb2AAABfdD/LOwAAAQDAEgwRgIhAMsttMITHy6uER2GTv4gjRE1
27 | RrjVspc/LQlNpHZvicv6AiEA7ZhwWaAt+djjYJ+NEL0NjmrvuJ6ql89YkwaZx15m
28 | PZgwDQYJKoZIhvcNAQELBQADggEBAFe0R6WbmGtKm3CJY2LMRbKwMKVu2zMJGHxL
29 | y7H+4U/CrFuvnqX3A9NWNqRW0LbEmytMJbP1AWItQgxFnNGHuSFwtf1S2s4b14nI
30 | +Dq4xMHT+LtoSXy5PIA6E7OSA2xkPvztxSoZjcjNKkTvmZRMT9f9aTAyDZPV7mz8
31 | KjuhyyeQlMu6EyONXhZdptOuh2coW+ktKgUbtGkOskjt68+2plXo+FutrHTRR3Hq
32 | EDRKd8CALHjctdBHAmaxu9NSd96NKYEN3nhVeVtWOauhgSbNDA/VZx9FbHhwhF6Z
33 | Mr7KRZ8XM+tY6gMvDZuAwicG4Rkazr9GOz4ll3ZWa6RkLL7skLg=
34 | -----END CERTIFICATE-----
35 | -----BEGIN CERTIFICATE-----
36 | MIIEqjCCA5KgAwIBAgIQAnmsRYvBskWr+YBTzSybsTANBgkqhkiG9w0BAQsFADBh
37 | MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
38 | d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
39 | QTAeFw0xNzExMjcxMjQ2MTBaFw0yNzExMjcxMjQ2MTBaMG4xCzAJBgNVBAYTAlVT
40 | MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
41 | b20xLTArBgNVBAMTJEVuY3J5cHRpb24gRXZlcnl3aGVyZSBEViBUTFMgQ0EgLSBH
42 | MTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALPeP6wkab41dyQh6mKc
43 | oHqt3jRIxW5MDvf9QyiOR7VfFwK656es0UFiIb74N9pRntzF1UgYzDGu3ppZVMdo
44 | lbxhm6dWS9OK/lFehKNT0OYI9aqk6F+U7cA6jxSC+iDBPXwdF4rs3KRyp3aQn6pj
45 | pp1yr7IB6Y4zv72Ee/PlZ/6rK6InC6WpK0nPVOYR7n9iDuPe1E4IxUMBH/T33+3h
46 | yuH3dvfgiWUOUkjdpMbyxX+XNle5uEIiyBsi4IvbcTCh8ruifCIi5mDXkZrnMT8n
47 | wfYCV6v6kDdXkbgGRLKsR4pucbJtbKqIkUGxuZI2t7pfewKRc5nWecvDBZf3+p1M
48 | pA8CAwEAAaOCAU8wggFLMB0GA1UdDgQWBBRVdE+yck/1YLpQ0dfmUVyaAYca1zAf
49 | BgNVHSMEGDAWgBQD3lA1VtFMu2bwo+IbG8OXsj3RVTAOBgNVHQ8BAf8EBAMCAYYw
50 | HQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMBIGA1UdEwEB/wQIMAYBAf8C
51 | AQAwNAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdp
52 | Y2VydC5jb20wQgYDVR0fBDswOTA3oDWgM4YxaHR0cDovL2NybDMuZGlnaWNlcnQu
53 | Y29tL0RpZ2lDZXJ0R2xvYmFsUm9vdENBLmNybDBMBgNVHSAERTBDMDcGCWCGSAGG
54 | /WwBAjAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BT
55 | MAgGBmeBDAECATANBgkqhkiG9w0BAQsFAAOCAQEAK3Gp6/aGq7aBZsxf/oQ+TD/B
56 | SwW3AU4ETK+GQf2kFzYZkby5SFrHdPomunx2HBzViUchGoofGgg7gHW0W3MlQAXW
57 | M0r5LUvStcr82QDWYNPaUy4taCQmyaJ+VB+6wxHstSigOlSNF2a6vg4rgexixeiV
58 | 4YSB03Yqp2t3TeZHM9ESfkus74nQyW7pRGezj+TC44xCagCQQOzzNmzEAP2SnCrJ
59 | sNE2DpRVMnL8J6xBRdjmOsC3N6cQuKuRXbzByVBjCqAA8t1L0I+9wXJerLPyErjy
60 | rMKWaBFLmfK/AHNF4ZihwPGOc7w6UHczBZXH5RFzJNnww+WnKuTPI0HfnVH8lg==
61 | -----END CERTIFICATE-----
62 |
--------------------------------------------------------------------------------
/conf.d/api.clicli.cc.conf:
--------------------------------------------------------------------------------
1 | server {
2 | listen 80;
3 | server_name api.clicli.cc;
4 | return 301 https://api.clicli.cc;
5 | }
6 | server {
7 | listen 443 ssl;
8 | server_name api.clicli.cc;
9 | ssl_certificate conf.d/api.clicli.cc.pem;
10 | ssl_certificate_key conf.d/api.clicli.cc.key;
11 | ssl_session_timeout 5m;
12 | ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
13 | ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
14 | ssl_prefer_server_ciphers on;
15 |
16 | location / {
17 | proxy_pass http://45.207.47.90:4000;
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/conf.d/api.clicli.cc.key:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIIEowIBAAKCAQEAnM+bapkzTf3choaoOipw0fB3LX3v3eOy9ATuHdektdpoUN/l
3 | trZW7JOfVKWYLkDlLfuF05mJI8oWpfL9nssCgTo/VezxFKmkJ2DTowVNNA5MA3De
4 | U29bci6DbUJRi5xu6KKNWzGgk82w97tcjmGj8/hYZziAGmykn5TAFIyKl97yhSLU
5 | 4EmOeI6u0N3n/hjXWvVUhotavYZgvUtvOlVw35hCn/mCAMxx79TvlfFQO//APJHH
6 | +xTyKkgn75YJV+72oY1iets9g3ClHbnYi7cPC79yR6CumpBNcTdEasRas+O/3NXb
7 | 3ACEvKpHBKEC0eUQtFiifsDdxwsCSzftwmc41wIDAQABAoIBADI4xYha/5T7eKz3
8 | JJrYa+C5GJpPyspweihwCckx/vUlOaKpSrt9Y5KKZw2nqXkq3JuhAkf2VPdK6n0E
9 | uVipoSg9PPqqk72v5TydZLrB4GuLJqo1dGcZc5q6reoIwvApTlYgdZBe8RRVXNfC
10 | wI5zVBy3jaylalXMNN9NN0V9i4e+5XSe43YnH0QbeTbFEDVl+Cg/fA7xaeN97W/o
11 | UsgIC1OvU4YjQ7pS6GeTLAvMxur8kZa2QrIehes15AJSpkuK0h9rjI4OgqD9xS5G
12 | 3bzSY3LuyiwQFYD4G4h7Qzq7Nk3wG85gk9bSVOnK8MPfLfO8pRmlSZxjD13vvEiz
13 | 6AQPARECgYEA2iQGbRftOglxGarh061PGK1rhsD7viClz07+VBYATxT8UPqXWR+I
14 | l/7D1d525klGzxZveVZVdeV7gm21RogUNKCjWp2/ES6CwxWUe6QFpJ315pXEcEVK
15 | ffDpBSKv7i1h9xOGAIU513sHAVpGwijNNmhqg0qv3sGojNPyGvo3SRECgYEAuAa0
16 | rCsY1cBj/uCkzpm1jw9Pdr5zYoWMI175F/2qWeezxHO6SBVz2SF8e9UX92/4Howa
17 | 9btjZQy6XHWeVLYLj3bQ/c/8WZyMep9iBbvc9EbXOQ11prRi5jwJrnvhHMz5RvwI
18 | ZoiaZO3fnS2bTh7WdOi2X9Mme8L0aA54qxBzo2cCgYAGaEp8B9ji/IYC7/8EHbIW
19 | Enn3ElISqpjUNwjHZYIK0J38ru+lIYT8mfIcpRUu/HYE/S63DK8j8GKpWRmbAcI+
20 | LX2+2qVTFt+mZUrgOtgjlrQzWrDTb2WZv2rIyNUMFO8st7kW6NLjHmz9QC6V42br
21 | szN1ucriqyONR2h0HGdlUQKBgApXfiHKzjt882GoeDqQEs72Wk3fCBb6UFTQiokZ
22 | nVAuIEEjC83vPrJuGlPPNuiV50i4MO+sVzqfi32UspAqJt4qHDaXUKQskwx1Fooh
23 | 85navU+cfQcgTgqIRzcCCTWYI04k7cftV1fislVf8cFjJEQvq8gY0qnT2+5ZGdjr
24 | NMRzAoGBAJErAslN14bqkwUsahcyjWttglt8ouEOgIbfvTWcB4wP4U54z+l39ynX
25 | sajoooI53xNegYO+Fk0WWa6TmQhOwRAvzHYUKET/DbcsP27Je/ps9/NMTxw8tDmM
26 | F5az2WhuwzJ9NvVKldPexXsYQwHVAg4SoDMkLJsmFqYSNuL1qTEo
27 | -----END RSA PRIVATE KEY-----
28 |
--------------------------------------------------------------------------------
/conf.d/api.clicli.cc.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIF8TCCBNmgAwIBAgIQDArv9/L5ibBdSxuy0I6B6TANBgkqhkiG9w0BAQsFADBu
3 | MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
4 | d3cuZGlnaWNlcnQuY29tMS0wKwYDVQQDEyRFbmNyeXB0aW9uIEV2ZXJ5d2hlcmUg
5 | RFYgVExTIENBIC0gRzEwHhcNMjExMjE5MDAwMDAwWhcNMjIxMjIwMjM1OTU5WjAY
6 | MRYwFAYDVQQDEw1hcGkuY2xpY2xpLmNjMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
7 | MIIBCgKCAQEAnM+bapkzTf3choaoOipw0fB3LX3v3eOy9ATuHdektdpoUN/ltrZW
8 | 7JOfVKWYLkDlLfuF05mJI8oWpfL9nssCgTo/VezxFKmkJ2DTowVNNA5MA3DeU29b
9 | ci6DbUJRi5xu6KKNWzGgk82w97tcjmGj8/hYZziAGmykn5TAFIyKl97yhSLU4EmO
10 | eI6u0N3n/hjXWvVUhotavYZgvUtvOlVw35hCn/mCAMxx79TvlfFQO//APJHH+xTy
11 | Kkgn75YJV+72oY1iets9g3ClHbnYi7cPC79yR6CumpBNcTdEasRas+O/3NXb3ACE
12 | vKpHBKEC0eUQtFiifsDdxwsCSzftwmc41wIDAQABo4IC3zCCAtswHwYDVR0jBBgw
13 | FoAUVXRPsnJP9WC6UNHX5lFcmgGHGtcwHQYDVR0OBBYEFN8TKiGYvwTlHjd1wDEu
14 | Z2Y0HBuKMBgGA1UdEQQRMA+CDWFwaS5jbGljbGkuY2MwDgYDVR0PAQH/BAQDAgWg
15 | MB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjA+BgNVHSAENzA1MDMGBmeB
16 | DAECATApMCcGCCsGAQUFBwIBFhtodHRwOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMw
17 | gYAGCCsGAQUFBwEBBHQwcjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNl
18 | cnQuY29tMEoGCCsGAQUFBzAChj5odHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20v
19 | RW5jcnlwdGlvbkV2ZXJ5d2hlcmVEVlRMU0NBLUcxLmNydDAJBgNVHRMEAjAAMIIB
20 | gAYKKwYBBAHWeQIEAgSCAXAEggFsAWoAdwApeb7wnjk5IfBWc59jpXflvld9nGAK
21 | +PlNXSZcJV3HhAAAAX3Q/kKIAAAEAwBIMEYCIQCuqad+IuQkI2LC0ni2nPXKg1ty
22 | ilnW7b0oC4N3cz9G3wIhALkopvo4G0eR+Cl3j/rXt7Uzr69kpHTL1NYh23FsvI2Y
23 | AHcAUaOw9f0BeZxWbbg3eI8MpHrMGyfL956IQpoN/tSLBeUAAAF90P5DBQAABAMA
24 | SDBGAiEA6z3pA9Z4nVJMenrlDXAzXrCrY8+YvaG/LY/a8//KyPsCIQCwqg5Z8I5I
25 | lR8A6ZCkGN3ptaNMLyZOSuYFX0XczPEpgQB2AN+lXqtogk8fbK3uuF9OPlrqzaIS
26 | pGpejjsSwCBEXCpzAAABfdD+QrcAAAQDAEcwRQIhAO1qXc3zda5R/yt+qmco9Znw
27 | e3QD9YWMuLJsK8TC0IxkAiBBZnoqd/rKeFvc6RnLJ4/lXvz/NjLUnvhdFIjGbIfZ
28 | uTANBgkqhkiG9w0BAQsFAAOCAQEAWRbjVhN3n7th60nb5cQVXnCuTKAnUJwmbFeS
29 | LZp6glVZfzR0dmNG/0wYSsvFullD/WDArikyEJXhivQAyglY+9ZqbdputZME7i4q
30 | 4rTHOyPkmGdSw6ix38IWcsNiG+n+r2z98wRWhWQ6oZEVBcIjSyg2rS2K3f4m82rf
31 | fzZw/wovA/Vp2UcOc76HfhPKqVeY7sxK8mQsxPoxXHLZlwC4MKaZmLbERplaDXKQ
32 | j6Krf0IwoZsp4Ufno1r/VtG/il7XXVli3CrJplyxRh9kTuRNYaGyPWB15KYaPZ1S
33 | T78h+aW5ZIoF1Ea04Ub4IY17BajyHUF+vMAK1IKuWkj/QtmVmA==
34 | -----END CERTIFICATE-----
35 | -----BEGIN CERTIFICATE-----
36 | MIIEqjCCA5KgAwIBAgIQAnmsRYvBskWr+YBTzSybsTANBgkqhkiG9w0BAQsFADBh
37 | MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
38 | d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
39 | QTAeFw0xNzExMjcxMjQ2MTBaFw0yNzExMjcxMjQ2MTBaMG4xCzAJBgNVBAYTAlVT
40 | MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
41 | b20xLTArBgNVBAMTJEVuY3J5cHRpb24gRXZlcnl3aGVyZSBEViBUTFMgQ0EgLSBH
42 | MTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALPeP6wkab41dyQh6mKc
43 | oHqt3jRIxW5MDvf9QyiOR7VfFwK656es0UFiIb74N9pRntzF1UgYzDGu3ppZVMdo
44 | lbxhm6dWS9OK/lFehKNT0OYI9aqk6F+U7cA6jxSC+iDBPXwdF4rs3KRyp3aQn6pj
45 | pp1yr7IB6Y4zv72Ee/PlZ/6rK6InC6WpK0nPVOYR7n9iDuPe1E4IxUMBH/T33+3h
46 | yuH3dvfgiWUOUkjdpMbyxX+XNle5uEIiyBsi4IvbcTCh8ruifCIi5mDXkZrnMT8n
47 | wfYCV6v6kDdXkbgGRLKsR4pucbJtbKqIkUGxuZI2t7pfewKRc5nWecvDBZf3+p1M
48 | pA8CAwEAAaOCAU8wggFLMB0GA1UdDgQWBBRVdE+yck/1YLpQ0dfmUVyaAYca1zAf
49 | BgNVHSMEGDAWgBQD3lA1VtFMu2bwo+IbG8OXsj3RVTAOBgNVHQ8BAf8EBAMCAYYw
50 | HQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMBIGA1UdEwEB/wQIMAYBAf8C
51 | AQAwNAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdp
52 | Y2VydC5jb20wQgYDVR0fBDswOTA3oDWgM4YxaHR0cDovL2NybDMuZGlnaWNlcnQu
53 | Y29tL0RpZ2lDZXJ0R2xvYmFsUm9vdENBLmNybDBMBgNVHSAERTBDMDcGCWCGSAGG
54 | /WwBAjAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BT
55 | MAgGBmeBDAECATANBgkqhkiG9w0BAQsFAAOCAQEAK3Gp6/aGq7aBZsxf/oQ+TD/B
56 | SwW3AU4ETK+GQf2kFzYZkby5SFrHdPomunx2HBzViUchGoofGgg7gHW0W3MlQAXW
57 | M0r5LUvStcr82QDWYNPaUy4taCQmyaJ+VB+6wxHstSigOlSNF2a6vg4rgexixeiV
58 | 4YSB03Yqp2t3TeZHM9ESfkus74nQyW7pRGezj+TC44xCagCQQOzzNmzEAP2SnCrJ
59 | sNE2DpRVMnL8J6xBRdjmOsC3N6cQuKuRXbzByVBjCqAA8t1L0I+9wXJerLPyErjy
60 | rMKWaBFLmfK/AHNF4ZihwPGOc7w6UHczBZXH5RFzJNnww+WnKuTPI0HfnVH8lg==
61 | -----END CERTIFICATE-----
62 |
--------------------------------------------------------------------------------
/conf.d/www.clicli.cc.conf:
--------------------------------------------------------------------------------
1 | server {
2 | listen 80;
3 | server_name www.clicli.cc clicli.cc;
4 | return 301 https://www.clicli.cc;
5 | }
6 | server {
7 | listen 443 ssl;
8 | server_name www.clicli.cc clicli.cc;
9 | ssl_certificate conf.d/www.clicli.cc.pem;
10 | ssl_certificate_key conf.d/www.clicli.cc.key;
11 | ssl_session_timeout 5m;
12 | ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
13 | ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
14 | ssl_prefer_server_ciphers on;
15 |
16 | location / {
17 | root /usr/share/nginx/html/fre;
18 | index index.html;
19 | try_files $uri $uri/ /index.html;
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/conf.d/www.clicli.cc.key:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIIEogIBAAKCAQEAxlWHj88LJXbmclOR+t5spRQ/E7UDHKrDK2cR0wLvW2mu9RIn
3 | B3Vn7L2ic25QcAEAuFT/0S0CWuupAIlHfK4I6een6Ci+eYvzsdk0DhV/LPv9Kwiu
4 | LypxF4jbw6JinE4CGGUGiqUxJbjfdkfFJhafYLkprbh3peZUEQvdNP2ZaJTGkoNW
5 | 09C3qYmlZ3jUzakbZEOj6dtmrnvCwXrEvOjl7tulsjFFRPj78DPVdDjtTk4BPsYD
6 | O1LpmnTxGqqv+s2bBhbN7bXKi6kmhHUUCA4RAmv+JtYpfq90Pi4rhhKNLq4UAU+o
7 | f7KSztaiBpw0T+wx6fD4mxzG1/a0TctGe4+ugwIDAQABAoIBABukZAZpBtar4aZh
8 | e2EJiv7e+YOXoN1n91efP9629AE7k4TYiNQDSv6112RbJZ7WpPEL97OBoGhnm+BV
9 | Qb9gyiE/hilXNGTgWpCZAyZLXLQ6UqiixxQPyD9NdcOoaDH8tVINEoJUT6tAPvTP
10 | P+z1DjV+2Q47PYHDvke57ZSrG6x1gOc4VIENfT7VFqeAqpOHv1LkW8R07zXMJm5P
11 | oTYgBmT9BE0PD12Vfvo8jzVdLqAfyUAUMZCguBlR4CGrzPfoRls7GdcrT2SoBD/7
12 | Uwp2MUxfmkD120jTaxtO8Vb5w1911yqXNzbXscxbVG8VAhBWAWqtooHRY1r7l3y9
13 | uMNkiGECgYEA7jfWa1JIYSogSpyk5AJfFyw/s+RiNeCP1hCTBaL7+6iGJ87zQrkS
14 | 0tK50Buc44kYQ7+V8Pq6tKXGMV8PuLG4riSGRiz/xzsGv3CYV+uel2zvvuBinfCG
15 | s9+RTy3iUXKUgWukzMywCSeYLTgnWXepwYSQ6WWHx4+EEV/TrOoaKCsCgYEA1SOK
16 | HjJFn/nTJL1II5LjsYVSu0Bd5srM646ZK/cxdHnroAXKIkFSnCVkrgQDPAOy7VCf
17 | SwMmrTDxE5pPnG38lyHDD61IsPjesRG+fi1US5qBRkQmaFWGTtbZC30KjhmtM7qK
18 | Wif4QwYAC7FvnBUTlacnTJqmnxVbFJkt39Q9TwkCgYBOgI4jjdkWVAiSLe7UyMdH
19 | Xqibgq6urJMZ6xpYKC677vxO0A8wNMc0PIdJQmBAR2R8pv0ljarLbznR+U64AbEn
20 | ihfJtniP0i7WFafOiXIY2qhjEZTOEX6CdjFvk2JajtTLlYqYhveX/LlUZYXqINoL
21 | UMFkeLX3GJ9gDmE2QWtfQwKBgG75eTGtxTi9cCWB9GypT6qfm2rp4bqIP1gqwC/3
22 | HiXiUT/Zo9xgHK42fgxpBHIcDu6nerko49trTyqAvxDY55qdNp4UAHQ8sF6LuZ6i
23 | 5XAT+1llpIXQegTUst/bdEJ2tgroBp9Yjlf/aMit00n2Y2MZTEoDf9v215yLASq4
24 | rE9ZAoGAPkRxMpCj3LS2JKbl7dL6ZkuxWdvscQ4xI9M03fGyIVoxCfOvy7j7SvWV
25 | HhxYn/7cIuaYAQf6mQswIhs9J3+hPz5t5X1U/6ztBqGpwLBpwBVt+4QUr+GrIXWH
26 | wHTxiMhO0LSj7ILZ3RMoJe9azB2BppZ+3rx+0BI11OKIeo1m6hE=
27 | -----END RSA PRIVATE KEY-----
28 |
--------------------------------------------------------------------------------
/conf.d/www.clicli.cc.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIF+TCCBOGgAwIBAgIQDys4pdU9iijh2SIGR1O9RjANBgkqhkiG9w0BAQsFADBu
3 | MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
4 | d3cuZGlnaWNlcnQuY29tMS0wKwYDVQQDEyRFbmNyeXB0aW9uIEV2ZXJ5d2hlcmUg
5 | RFYgVExTIENBIC0gRzEwHhcNMjExMjE5MDAwMDAwWhcNMjIxMjIwMjM1OTU5WjAY
6 | MRYwFAYDVQQDEw13d3cuY2xpY2xpLmNjMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
7 | MIIBCgKCAQEAxlWHj88LJXbmclOR+t5spRQ/E7UDHKrDK2cR0wLvW2mu9RInB3Vn
8 | 7L2ic25QcAEAuFT/0S0CWuupAIlHfK4I6een6Ci+eYvzsdk0DhV/LPv9KwiuLypx
9 | F4jbw6JinE4CGGUGiqUxJbjfdkfFJhafYLkprbh3peZUEQvdNP2ZaJTGkoNW09C3
10 | qYmlZ3jUzakbZEOj6dtmrnvCwXrEvOjl7tulsjFFRPj78DPVdDjtTk4BPsYDO1Lp
11 | mnTxGqqv+s2bBhbN7bXKi6kmhHUUCA4RAmv+JtYpfq90Pi4rhhKNLq4UAU+of7KS
12 | ztaiBpw0T+wx6fD4mxzG1/a0TctGe4+ugwIDAQABo4IC5zCCAuMwHwYDVR0jBBgw
13 | FoAUVXRPsnJP9WC6UNHX5lFcmgGHGtcwHQYDVR0OBBYEFN0GChB/nlcOVLW6B7kE
14 | rClSpb8MMCMGA1UdEQQcMBqCDXd3dy5jbGljbGkuY2OCCWNsaWNsaS5jYzAOBgNV
15 | HQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMD4GA1Ud
16 | IAQ3MDUwMwYGZ4EMAQIBMCkwJwYIKwYBBQUHAgEWG2h0dHA6Ly93d3cuZGlnaWNl
17 | cnQuY29tL0NQUzCBgAYIKwYBBQUHAQEEdDByMCQGCCsGAQUFBzABhhhodHRwOi8v
18 | b2NzcC5kaWdpY2VydC5jb20wSgYIKwYBBQUHMAKGPmh0dHA6Ly9jYWNlcnRzLmRp
19 | Z2ljZXJ0LmNvbS9FbmNyeXB0aW9uRXZlcnl3aGVyZURWVExTQ0EtRzEuY3J0MAkG
20 | A1UdEwQCMAAwggF9BgorBgEEAdZ5AgQCBIIBbQSCAWkBZwB2AEalVet1+pEgMLWi
21 | iWn0830RLEF0vv1JuIWr8vxw/m1HAAABfdD/MF0AAAQDAEcwRQIhAI8K2pTQIy1O
22 | SQ3Dvm4KvHf9okiJ5ormOaleCqSb2tCxAiBoZyNRrEt0/EFS8DdW2AZnKMtgOPm1
23 | WAzU0d5rZllZPwB2AFGjsPX9AXmcVm24N3iPDKR6zBsny/eeiEKaDf7UiwXlAAAB
24 | fdD/MIIAAAQDAEcwRQIgN1/C7MtT90aWvorS8/TtTGBbUF0/dQBMVxMQkfALx+AC
25 | IQDwHlYShXAVFSSDaKh018bcRdny/gM98RtP2mempUvs2gB1AEHIyrHfIkZKEMah
26 | OglCh15OMYsbA+vrS8do8JBilgb2AAABfdD/MAQAAAQDAEYwRAIgVeq0Ze4RR1il
27 | Dzpw+InHEIE9AJFhpt1jxTWJT99Zrz8CIG+qvGOyLV8PdhwYBGwjVx0dOvctiok8
28 | uWo/sMvjMLmoMA0GCSqGSIb3DQEBCwUAA4IBAQAqveNjOCBFYSkLCtA9XvFady+u
29 | j4rKJgONILJs+Dzroo61Qm0d3XMgRkHIhfPdZjvAeF1LJhH7xCmyS2P64fjMTm4k
30 | UKy3PJB68juFKAjmyxix/5jmZ9s+CLNztLqKm5vSTaeO1fPn9V4kBogSFkcTpw79
31 | ht+sVUx8mAqExqvselV245CUw43+4c3xnIxU8oUif0Ot8pkMWQ8oUgdI8JCrJaaX
32 | cgQfjuZU8NoF9zKKu1P0Oj24LYHgCGCsyJ19f319fPuFIdb9RZCRvu5UOLdV4pn+
33 | F49q+4bbYHrHmxDTZBuRZqldHikRT7N1PDso2NEgfXPSzRFCqQWz/hIVpQrT
34 | -----END CERTIFICATE-----
35 | -----BEGIN CERTIFICATE-----
36 | MIIEqjCCA5KgAwIBAgIQAnmsRYvBskWr+YBTzSybsTANBgkqhkiG9w0BAQsFADBh
37 | MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
38 | d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
39 | QTAeFw0xNzExMjcxMjQ2MTBaFw0yNzExMjcxMjQ2MTBaMG4xCzAJBgNVBAYTAlVT
40 | MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
41 | b20xLTArBgNVBAMTJEVuY3J5cHRpb24gRXZlcnl3aGVyZSBEViBUTFMgQ0EgLSBH
42 | MTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALPeP6wkab41dyQh6mKc
43 | oHqt3jRIxW5MDvf9QyiOR7VfFwK656es0UFiIb74N9pRntzF1UgYzDGu3ppZVMdo
44 | lbxhm6dWS9OK/lFehKNT0OYI9aqk6F+U7cA6jxSC+iDBPXwdF4rs3KRyp3aQn6pj
45 | pp1yr7IB6Y4zv72Ee/PlZ/6rK6InC6WpK0nPVOYR7n9iDuPe1E4IxUMBH/T33+3h
46 | yuH3dvfgiWUOUkjdpMbyxX+XNle5uEIiyBsi4IvbcTCh8ruifCIi5mDXkZrnMT8n
47 | wfYCV6v6kDdXkbgGRLKsR4pucbJtbKqIkUGxuZI2t7pfewKRc5nWecvDBZf3+p1M
48 | pA8CAwEAAaOCAU8wggFLMB0GA1UdDgQWBBRVdE+yck/1YLpQ0dfmUVyaAYca1zAf
49 | BgNVHSMEGDAWgBQD3lA1VtFMu2bwo+IbG8OXsj3RVTAOBgNVHQ8BAf8EBAMCAYYw
50 | HQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMBIGA1UdEwEB/wQIMAYBAf8C
51 | AQAwNAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdp
52 | Y2VydC5jb20wQgYDVR0fBDswOTA3oDWgM4YxaHR0cDovL2NybDMuZGlnaWNlcnQu
53 | Y29tL0RpZ2lDZXJ0R2xvYmFsUm9vdENBLmNybDBMBgNVHSAERTBDMDcGCWCGSAGG
54 | /WwBAjAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BT
55 | MAgGBmeBDAECATANBgkqhkiG9w0BAQsFAAOCAQEAK3Gp6/aGq7aBZsxf/oQ+TD/B
56 | SwW3AU4ETK+GQf2kFzYZkby5SFrHdPomunx2HBzViUchGoofGgg7gHW0W3MlQAXW
57 | M0r5LUvStcr82QDWYNPaUy4taCQmyaJ+VB+6wxHstSigOlSNF2a6vg4rgexixeiV
58 | 4YSB03Yqp2t3TeZHM9ESfkus74nQyW7pRGezj+TC44xCagCQQOzzNmzEAP2SnCrJ
59 | sNE2DpRVMnL8J6xBRdjmOsC3N6cQuKuRXbzByVBjCqAA8t1L0I+9wXJerLPyErjy
60 | rMKWaBFLmfK/AHNF4ZihwPGOc7w6UHczBZXH5RFzJNnww+WnKuTPI0HfnVH8lg==
61 | -----END CERTIFICATE-----
62 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "nfes-next",
3 | "version": "1.0.0",
4 | "description": "实验性 no bundle all streams",
5 | "main": "index.js",
6 | "dependencies": {
7 | "fre": "1.13.3",
8 | "pnpm": "^6.24.1",
9 | "blueimp-md5": "^2.12.0",
10 | "devtools-detector": "^1.0.21",
11 | "snarkdown": "^1.2.2"
12 | },
13 | "devDependencies": {
14 | "@babel/core": "^7.6.4",
15 | "@babel/plugin-transform-react-jsx": "^7.3.0",
16 | "@babel/preset-env": "^7.6.3",
17 | "babel-loader": "^8.0.6",
18 | "clean-webpack-plugin": "^3.0.0",
19 | "cross-env": "^6.0.3",
20 | "css-loader": "^3.2.0",
21 | "html-webpack-plugin": "^3.2.0",
22 | "mini-css-extract-plugin": "^0.8.0",
23 | "style-loader": "^1.0.1",
24 | "stylus": "^0.54.7",
25 | "stylus-loader": "^3.0.2",
26 | "to-string-loader": "^1.1.6",
27 | "webpack": "^4.41.1",
28 | "webpack-cli": "^3.3.9",
29 | "webpack-dev-server": "^3.8.2"
30 | },
31 | "scripts": {
32 | "test": "echo \"Error: no test specified\" && exit 1",
33 | "build:fre": "pnpm run build --filter @clicli/fre",
34 | "dev:fre": "pnpm run start --filter @clicli/fre",
35 | "build:admin":"pnpm run build --filter @clicli/admin",
36 | "dev:admin":"pnpm run dev --filter @clicli/admin"
37 | },
38 | "repository": {
39 | "type": "git",
40 | "url": "git@git.dev.sh.ctripcorp.com:changhaozhao/nfes-next"
41 | },
42 | "keywords": [],
43 | "author": "",
44 | "license": "ISC"
45 | }
46 |
--------------------------------------------------------------------------------
/packages/fre/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": [
3 | [
4 | "@babel/plugin-transform-react-jsx",
5 | {
6 | "pragma": "h"
7 | }
8 | ]
9 | ]
10 | }
--------------------------------------------------------------------------------
/packages/fre/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Runtime data
9 | pids
10 | *.pid
11 | *.seed
12 | *.pid.lock
13 |
14 | # Directory for instrumented libs generated by jscoverage/JSCover
15 | lib-cov
16 |
17 | # Coverage directory used by tools like istanbul
18 | coverage
19 |
20 | # nyc test coverage
21 | .nyc_output
22 |
23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
24 | .grunt
25 |
26 | # Bower dependency directory (https://bower.io/)
27 | bower_components
28 |
29 | # node-waf configuration
30 | .lock-wscript
31 |
32 | # Compiled binary addons (https://nodejs.org/api/addons.html)
33 | build/Release
34 |
35 | # Dependency directories
36 | node_modules/
37 | jspm_packages/
38 |
39 | # TypeScript v1 declaration files
40 | typings/
41 |
42 | # Optional npm cache directory
43 | .npm
44 |
45 | # Optional eslint cache
46 | .eslintcache
47 |
48 | # Optional REPL history
49 | .node_repl_history
50 |
51 | # Output of 'npm pack'
52 | *.tgz
53 |
54 | # Yarn Integrity file
55 | .yarn-integrity
56 |
57 | # dotenv environment variables file
58 | .env
59 |
60 | # next.js build output
61 | .next
62 |
63 | .idea/
64 | server/config.js
65 | server/hcy.js
66 | server/san.js
--------------------------------------------------------------------------------
/packages/fre/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/packages/fre/README.md:
--------------------------------------------------------------------------------
1 | # fre-clicli-home
2 | > 新版c站首页,fre 强力驱动
3 |
4 | ### 技术栈
5 | * webpack4
6 | * fre
7 | * stylus
8 |
9 | ### 启动
10 |
11 | ```console
12 | yarn start
13 | ```
14 |
--------------------------------------------------------------------------------
/packages/fre/dist/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | c站-clicli弹幕网_(⁄•⁄ω⁄•⁄) 社保~ clicli.cc
8 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/packages/fre/dist/main.css:
--------------------------------------------------------------------------------
1 | .tab {
2 | background: #946ce6;
3 | height: auto;
4 | }
5 | .tab li {
6 | display: inline-block;
7 | padding: 20px;
8 | cursor: pointer;
9 | color: #fff;
10 | border-top: 3px solid #946ce6;
11 | }
12 | .tab li:hover {
13 | border-top-color: #fff;
14 | }
15 | .active {
16 | border-top-color: #fff !important;
17 | }
18 | .tab-right {
19 | float: right;
20 | }
21 |
22 | .post-detail {
23 | width: 100%;
24 | display: flex;
25 | }
26 | .left {
27 | width: 520px;
28 | padding: 20px 10px;
29 | }
30 | article img[alt=suo] {
31 | width: 100%;
32 | border-radius: 2px;
33 | }
34 | article img {
35 | max-width: 100%;
36 | border-radius: 2px;
37 | }
38 | article h1 {
39 | font-size: 18px;
40 | font-weight: bold;
41 | padding: 0 10px;
42 | margin: 20px 0;
43 | border-left: 5px solid #946ce6;
44 | }
45 | article h2 {
46 | font-size: 16px;
47 | font-weight: bold;
48 | padding: 0 10px;
49 | margin: 18px 0;
50 | border-left: 5px solid #946ce6;
51 | }
52 | article h3 {
53 | font-size: 14px;
54 | font-weight: bold;
55 | padding: 0 10px;
56 | margin: 16px 0;
57 | border-left: 5px solid #946ce6;
58 | }
59 | article blockquote {
60 | word-wrap: break-word;
61 | background: rgba(148,108,230,0.1);
62 | color: #946ce6;
63 | padding: 10px;
64 | margin: 10px 0;
65 | }
66 | article a {
67 | text-decoration: none;
68 | color: #946ce6;
69 | padding: 0 5px;
70 | font-weight: bold;
71 | }
72 | .right {
73 | width: 600px;
74 | padding: 10px;
75 | margin: 20px auto;
76 | }
77 | .right .info .user {
78 | display: flex;
79 | align-items: center;
80 | }
81 | .right .info .avatar,
82 | .right .info .avatar img {
83 | width: 60px;
84 | height: 60px;
85 | border-radius: 30px;
86 | }
87 | .right .info span {
88 | padding: 10px;
89 | }
90 | .right .info .uid {
91 | color: #bbb;
92 | }
93 | .right .title {
94 | display: flex;
95 | padding: 10px;
96 | align-items: center;
97 | }
98 | .right .title h1 {
99 | overflow: hidden;
100 | padding: 0;
101 | display: inline-block;
102 | }
103 | .right .title .pv {
104 | background: #946ce6;
105 | padding: 10px 15px !important;
106 | border-radius: 40px 40px 40px 0;
107 | color: #fff;
108 | font-size: 14px;
109 | text-align: center;
110 | margin-left: 20px;
111 | }
112 | .right .copyright {
113 | padding: 10px;
114 | font-size: 20px;
115 | color: #888;
116 | }
117 | .right .other {
118 | padding: 20px 0;
119 | display: none;
120 | }
121 |
122 | .ep {
123 | position: relative;
124 | }
125 | .mark {
126 | background: rgba(0,0,0,0.8);
127 | position: fixed;
128 | top: 0;
129 | bottom: 0;
130 | right: 0;
131 | left: 0;
132 | }
133 | .ep {
134 | width: 800px;
135 | height: 450px;
136 | position: fixed;
137 | top: 50%;
138 | left: 50%;
139 | transform: translate(-50%, -50%);
140 | z-index: 1;
141 | }
142 | .close {
143 | position: absolute;
144 | top: 0;
145 | right: -50px;
146 | z-index: 1;
147 | color: #fff;
148 | cursor: pointer;
149 | padding: 10px;
150 | }
151 | .close .icon-close {
152 | font-size: 24px;
153 | }
154 | video {
155 | width: 100%;
156 | height: 100%;
157 | }
158 |
159 | .video-list {
160 | width: 600px;
161 | float: left;
162 | padding: 10px 0;
163 | }
164 | .video-list .item {
165 | display: flex;
166 | align-items: center;
167 | padding: 10px;
168 | cursor: pointer;
169 | }
170 | .video-list .item img {
171 | width: 40px;
172 | height: 40px;
173 | border-radius: 50%;
174 | margin: 6px 10px;
175 | }
176 | .video-list .item span {
177 | padding: 10px;
178 | }
179 | .video-list .item:nth-of-type(even) {
180 | background: #f4f6fa;
181 | }
182 | .video-list .item2 {
183 | display: inline-block;
184 | background: #f4f6fa;
185 | padding: 10px;
186 | border-radius: 2px;
187 | margin: 10px;
188 | cursor: pointer;
189 | }
190 |
191 | .footer {
192 | background: #f4f6fa;
193 | display: flex;
194 | padding: 30px;
195 | text-align: center;
196 | color: #888;
197 | }
198 | .footer .links a {
199 | display: inline-block;
200 | padding: 20px;
201 | }
202 | .footer .mail {
203 | background: #946ce6;
204 | color: #fff;
205 | border-radius: 2px;
206 | padding: 2px 10px;
207 | margin: 10px 10px 10px 0;
208 | }
209 |
210 | .call {
211 | background: #946ce6;
212 | color: #fff;
213 | margin: 0 auto;
214 | padding: 2px 50px;
215 | display: inline-block;
216 | border-radius: 0 0 2px 2px;
217 | }
218 | * {
219 | padding: 0;
220 | margin: 0;
221 | }
222 | body,
223 | :host {
224 | font: 14px '14px -apple-system,BlinkMacSystemFont,Helvetica Neue,Helvetica,Arial,PingFang SC,Hiragino Sans GB,Microsoft YaHei,sans-serif';
225 | color: #444;
226 | padding: 0;
227 | margin: 0;
228 | }
229 | a {
230 | text-decoration: none;
231 | color: #444;
232 | }
233 | li {
234 | list-style: none;
235 | }
236 | input,
237 | button {
238 | outline: none;
239 | }
240 | .wrap {
241 | width: 1160px;
242 | margin: 0 auto;
243 | position: relative;
244 | }
245 | h1 {
246 | font-size: 28px;
247 | font-weight: normal;
248 | padding: 30px 0;
249 | }
250 | img {
251 | background: #f4f6fa;
252 | }
253 |
254 | header {
255 | height: 180px;
256 | box-shadow: 2px 2px 0px rgba(5,20,50,0.1);
257 | background: url("https://ae01.alicdn.com/kf/U251ceb70165240ef865c7bed275579feN.jpg") center top;
258 | background-size: auto 100%;
259 | }
260 | .header {
261 | position: absolute;
262 | color: #fff;
263 | top: 0;
264 | left: 0;
265 | right: 0;
266 | text-shadow: 0 1px 1px rgba(0,0,0,0.24);
267 | }
268 | .header .nav {
269 | padding: 20px 0;
270 | }
271 | .header .nav li {
272 | display: inline-block;
273 | cursor: pointer;
274 | padding: 2px 10px;
275 | border-radius: 10px;
276 | transition: 0.3s;
277 | }
278 | .header .nav li:hover {
279 | background: #946ce6;
280 | }
281 | .header .wrap {
282 | display: flex;
283 | align-items: center;
284 | }
285 | .header .logo {
286 | margin: 0 10px;
287 | width: 150px;
288 | height: 86px;
289 | background: url("https://p.pstatp.com/origin/ffe900005cf65f21f262");
290 | background-size: contain;
291 | }
292 | .header .logo h1 {
293 | font-size: 14px;
294 | display: inline-block;
295 | padding-bottom: 5px;
296 | }
297 | .header a {
298 | color: #fff;
299 | margin: 0 10px;
300 | }
301 | .header li.active {
302 | background: linear-gradient(90deg, #946ce6, #7e5fd9);
303 | }
304 | .header .biu {
305 | position: absolute;
306 | right: 0;
307 | }
308 | .header .biu .login {
309 | padding: 2px 5px;
310 | border-radius: 10px;
311 | transition: 0.3s;
312 | background: transparent;
313 | }
314 | .header .biu .login:hover {
315 | background: #946ce6;
316 | }
317 | .header .biu .user-center {
318 | background: linear-gradient(90deg, #946ce6, #7e5fd9);
319 | border-radius: 2px;
320 | padding: 5px 30px;
321 | margin-left: 10px;
322 | }
323 | .header .call {
324 | background: #fff;
325 | margin: 0 auto;
326 | padding: 2px 10px;
327 | display: inline-block;
328 | border-radius: 10px;
329 | color: #946ce6;
330 | border: 1px solid #946ce6;
331 | margin-left: 10px;
332 | }
333 |
334 | .search {
335 | position: absolute;
336 | top: 50%;
337 | left: 50%;
338 | transform: translate(-50%, -70%);
339 | }
340 | .search input {
341 | padding: 10px 15px;
342 | border-radius: 22px;
343 | border: 3px solid #946ce6;
344 | background: #fff;
345 | width: 300px;
346 | }
347 | .search span {
348 | position: absolute;
349 | right: 10px;
350 | top: 8px;
351 | }
352 | .search .icon-search {
353 | font-size: 24px;
354 | font-weight: bold;
355 | color: #946ce6;
356 | }
357 |
358 | .recommend {
359 | width: 850px;
360 | }
361 | .recommend li {
362 | width: 20%;
363 | display: inline-block;
364 | cursor: pointer;
365 | }
366 | .recommend .title {
367 | width: 150px;
368 | height: 40px;
369 | overflow: hidden;
370 | margin: 10px 0;
371 | }
372 | .recommend .cover,
373 | .recommend .cover img {
374 | width: 150px;
375 | height: 210px;
376 | box-shadow: 2px 2px 0px rgba(5,20,50,0.1);
377 | border-radius: 2px;
378 | object-fit: cover;
379 | }
380 |
381 | .rank {
382 | width: 310px;
383 | }
384 | .rank .title {
385 | padding: 0 10px;
386 | height: 21px;
387 | overflow: hidden;
388 | }
389 | .rank .cover,
390 | .rank .cover img {
391 | width: 150px;
392 | height: 210px;
393 | box-shadow: 2px 2px 0px rgba(5,20,50,0.1);
394 | border-radius: 2px;
395 | object-fit: cover;
396 | }
397 | .rank .current {
398 | display: flex;
399 | position: relative;
400 | padding: 0 7px 14px 7px;
401 | }
402 | .rank .current .title {
403 | font-size: 16px;
404 | transition: 0.3s;
405 | }
406 | .rank .current .bom {
407 | position: absolute;
408 | display: flex;
409 | align-items: baseline;
410 | bottom: 12px;
411 | }
412 | .rank .current .bom .tag {
413 | font-size: 12px;
414 | padding: 0 10px;
415 | color: #888;
416 | }
417 | .rank .current .bom .idx {
418 | font-size: 60px;
419 | color: #946ce6;
420 | font-weight: bold;
421 | position: relative;
422 | bottom: -18px;
423 | }
424 | .rank .current:hover .title {
425 | color: #946ce6;
426 | }
427 | .rank li {
428 | display: flex;
429 | padding: 7px;
430 | cursor: pointer;
431 | }
432 | .rank li span {
433 | font-size: 16px;
434 | font-weight: bold;
435 | color: #888;
436 | }
437 | .rank li .active {
438 | color: #946ce6;
439 | }
440 | .rank li a,
441 | .rank li .info {
442 | width: 0;
443 | flex-grow: 1;
444 | }
445 | .rank li .title {
446 | transition: 0.3s;
447 | overflow: hidden;
448 | text-overflow: ellipsis;
449 | white-space: nowrap;
450 | }
451 | .rank li:hover .title {
452 | color: #946ce6;
453 | }
454 |
455 | .week-list .headline {
456 | display: flex;
457 | align-items: center;
458 | }
459 | .week-list .headline ul,
460 | .week-list .headline button {
461 | background: none;
462 | border: 0;
463 | margin: 10px;
464 | font-size: 16px;
465 | padding: 5px;
466 | }
467 | .week-list .headline ul .active,
468 | .week-list .headline button .active {
469 | color: #946ce6;
470 | position: relative;
471 | }
472 | .week-list .headline ul .active:after,
473 | .week-list .headline button .active:after {
474 | content: "";
475 | position: absolute;
476 | height: 3px;
477 | width: 10px;
478 | background: #946ce6;
479 | bottom: 0;
480 | left: 50%;
481 | transform: translateX(-50%);
482 | }
483 | .week-list .headline button:active {
484 | transform: scale(0.97);
485 | }
486 | .week-list .posts {
487 | height: 407px;
488 | overflow: auto;
489 | }
490 | .week-list .posts li {
491 | display: inline-block;
492 | width: 20%;
493 | text-align: center;
494 | cursor: pointer;
495 | }
496 | .week-list .posts li .post {
497 | padding-right: 20px;
498 | }
499 | .week-list .posts li .cover,
500 | .week-list .posts li img {
501 | height: 140px;
502 | width: 100%;
503 | object-fit: cover;
504 | box-shadow: 2px 2px 0px rgba(5,20,50,0.1);
505 | border-radius: 2px;
506 | }
507 | .week-list .posts li .title {
508 | height: 40px;
509 | overflow: hidden;
510 | padding: 10px 0;
511 | }
512 |
513 | .ugc-list {
514 | background: #f4f6fa;
515 | padding-bottom: 50px;
516 | }
517 | .ugc-list .posts li {
518 | display: inline-block;
519 | width: 275px;
520 | text-align: center;
521 | margin-right: 20px;
522 | margin-bottom: 20px;
523 | }
524 | .ugc-list .posts li .post {
525 | background: #fff;
526 | border-radius: 2px;
527 | box-shadow: 2px 2px 0px rgba(5,20,50,0.1);
528 | }
529 | .ugc-list .posts li .cover,
530 | .ugc-list .posts li .cover img {
531 | height: 160px;
532 | width: 100%;
533 | object-fit: cover;
534 | }
535 | .ugc-list .posts li .title {
536 | overflow: hidden;
537 | padding-left: 10px;
538 | height: 18px;
539 | }
540 | .ugc-list .posts li .info {
541 | display: flex;
542 | padding: 10px;
543 | align-items: center;
544 | }
545 | .ugc-list .posts li .uqq,
546 | .ugc-list .posts li .uqq img {
547 | height: 40px;
548 | width: 40px;
549 | border-radius: 50%;
550 | }
551 | .ugc-list .posts li:nth-child(4n) {
552 | margin-right: 0 !important;
553 | }
554 |
555 | .post-list {
556 | margin-bottom: 30px !important;
557 | }
558 | .post-list li {
559 | width: 176.6px;
560 | display: inline-block;
561 | margin-right: 20px;
562 | box-sizing: border-box;
563 | cursor: pointer;
564 | }
565 | .post-list .title {
566 | width: 170px;
567 | height: 40px;
568 | overflow: hidden;
569 | padding: 10px 0;
570 | }
571 | .post-list .cover,
572 | .post-list .cover img {
573 | width: 100%;
574 | height: 230px;
575 | box-shadow: 2px 2px 0px rgba(5,20,50,0.1);
576 | border-radius: 2px;
577 | object-fit: cover;
578 | }
579 | .post-list li:nth-child(6n) {
580 | margin-right: 0;
581 | }
582 |
583 | * {
584 | padding: 0;
585 | margin: 0;
586 | }
587 | body {
588 | font: 14px '14px -apple-system,BlinkMacSystemFont,Helvetica Neue,Helvetica,Arial,PingFang SC,Hiragino Sans GB,Microsoft YaHei,sans-serif';
589 | color: #444;
590 | padding: 0;
591 | margin: 0;
592 | min-width: 1200px;
593 | }
594 | a {
595 | text-decoration: none;
596 | color: #444;
597 | }
598 | li {
599 | list-style: none;
600 | }
601 | input,
602 | button {
603 | outline: none;
604 | }
605 | .wrap {
606 | width: 1160px;
607 | margin: 0 auto;
608 | position: relative;
609 | }
610 | h1 {
611 | font-size: 28px;
612 | font-weight: normal;
613 | padding: 30px 0;
614 | }
615 | img {
616 | background: #f4f6fa;
617 | }
618 | ::-webkit-scrollbar {
619 | background: #fff;
620 | width: 5px;
621 | }
622 | ::-webkit-scrollbar-thumb {
623 | background: #946ce6;
624 | border-radius: 2px;
625 | }
626 | ::-webkit-scrollbar-track {
627 | background: #f4f4fa;
628 | }
629 |
630 | @media screen and (max-width: 480px) {
631 | h1 {
632 | padding: 20px 10px;
633 | font-size: 24px;
634 | }
635 | .rank,
636 | .footer,
637 | .biu,
638 | .logo,
639 | .tab-right {
640 | display: none;
641 | }
642 | body {
643 | min-width: 100%;
644 | }
645 | .wrap {
646 | width: 100%;
647 | }
648 | nav a {
649 | margin: 0 !important;
650 | }
651 | nav .active {
652 | margin-left: 10px;
653 | }
654 | header {
655 | height: 120px;
656 | }
657 | .search {
658 | transform: translate(-50%, 0);
659 | }
660 | .cover,
661 | .cover img {
662 | width: 100% !important;
663 | height: 180px !important;
664 | box-shadow: none !important;
665 | }
666 | .recommend {
667 | box-sizing: border-box;
668 | padding: 1px;
669 | height: 800px;
670 | overflow: hidden;
671 | }
672 | .recommend li {
673 | width: 33.3%;
674 | padding: 1px;
675 | box-sizing: border-box;
676 | }
677 | .recommend .title {
678 | width: 100%;
679 | }
680 | .week-list {
681 | padding-bottom: 20px;
682 | }
683 | .week-list .posts {
684 | height: auto;
685 | padding: 0 10px;
686 | box-sizing: border-box;
687 | }
688 | .week-list .posts li {
689 | width: 25%;
690 | }
691 | .week-list h1 {
692 | display: none;
693 | }
694 | .week-list .headline ul {
695 | display: flex;
696 | }
697 | .week-list .headline button {
698 | margin: 3px !important;
699 | }
700 | .week-list .cover,
701 | .week-list img {
702 | height: 80px !important;
703 | width: 80px !important;
704 | border-radius: 40px !important;
705 | }
706 | .week-list .title {
707 | height: 30px !important;
708 | }
709 | .post-list {
710 | box-sizing: border-box;
711 | padding: 1px;
712 | }
713 | .post-list li {
714 | width: 33.3%;
715 | margin: 0;
716 | box-sizing: border-box;
717 | padding: 1px;
718 | }
719 | .post-list li .title {
720 | width: 100%;
721 | }
722 | .right {
723 | box-sizing: border-box;
724 | width: 100%;
725 | }
726 | .right .info {
727 | width: 100%;
728 | }
729 | .video-list {
730 | width: 100%;
731 | box-sizing: border-box;
732 | }
733 | .ep {
734 | width: 100%;
735 | height: auto;
736 | }
737 | .close {
738 | right: 50%;
739 | transform: translate(50%, 0);
740 | top: -50px;
741 | }
742 | .ugc-list {
743 | padding: 5px 5px 20px 5px;
744 | }
745 | .ugc-list li {
746 | width: 50% !important;
747 | margin: 0 !important;
748 | padding: 5px !important;
749 | box-sizing: border-box;
750 | }
751 | .ugc-list li .post {
752 | box-shadow: none !important;
753 | }
754 | .ugc-list li .post .cover {
755 | height: 120px !important;
756 | }
757 | .ugc-list li .post .cover img {
758 | height: 120px !important;
759 | }
760 | }
761 |
762 |
--------------------------------------------------------------------------------
/packages/fre/docs/404.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | c站-clicli弹幕网_(⁄•⁄ω⁄•⁄) 社保~ clicli.us
8 |
10 |
11 |
12 |
13 | c站已更换域名为 clicli.cc 4s
14 |
21 |
22 |
--------------------------------------------------------------------------------
/packages/fre/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | c站-clicli弹幕网_(⁄•⁄ω⁄•⁄) 社保~ clicli.us
8 |
10 |
11 |
12 |
13 | c站已更换域名为 clicli.cc 4s
14 |
21 |
22 |
--------------------------------------------------------------------------------
/packages/fre/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@clicli/fre",
3 | "version": "1.0.0",
4 | "description": "clicli new home page with fre",
5 | "main": "index.js",
6 | "scripts": {
7 | "build": "cross-env NODE_ENV=production webpack --mode production",
8 | "start": "cross-env NODE_ENV=development webpack-dev-server --mode development"
9 | },
10 | "repository": {
11 | "type": "git",
12 | "url": "git+https://github.com/cliclitv/fre-clicli-home.git"
13 | },
14 | "keywords": [],
15 | "author": "",
16 | "license": "ISC",
17 | "bugs": {
18 | "url": "https://github.com/cliclitv/fre-clicli-home/issues"
19 | },
20 | "homepage": "https://github.com/cliclitv/fre-clicli-home#readme",
21 | "dependencies": {},
22 | "devDependencies": {}
23 | }
--------------------------------------------------------------------------------
/packages/fre/src/api/get.js:
--------------------------------------------------------------------------------
1 | import { get } from '../public/js/fetch'
2 |
3 | export function getPost(type, tag, page, pageSize, status, uid) {
4 | return get(`//api.clicli.cc/posts?status=${status || 'public'}&sort=${type}&tag=${tag}&uid=${uid || ''}&page=${page}&pageSize=${pageSize}`)
5 | }
6 |
7 | export function getRank() {
8 | return get('//api.clicli.cc/rank')
9 | }
10 |
11 | export function getPostDetail(pid) {
12 | return get(`//api.clicli.cc/post/${pid}`)
13 | }
14 |
15 | export function getVideoList(pid) {
16 | return get(`//api.clicli.cc/videos?pid=${pid}&page=1&pageSize=150`)
17 | }
18 |
19 | export function getPlayUrl(url) {
20 | return get(`//api.clicli.cc/play?url=${url}`)
21 | }
22 |
23 | export function getPv(pid) {
24 | return get(`//api.clicli.cc/pv/${pid}`)
25 | }
26 |
27 | export function getSearch(key) {
28 | return get(`//api.clicli.cc/search/posts?key=${key}`)
29 | }
30 |
--------------------------------------------------------------------------------
/packages/fre/src/component/comment-list/index.js:
--------------------------------------------------------------------------------
1 | //todo
--------------------------------------------------------------------------------
/packages/fre/src/component/footer/index.js:
--------------------------------------------------------------------------------
1 | import { h } from 'fre'
2 | import './index.styl'
3 |
4 | export default function Footer() {
5 | const concat = {
6 | 风车动漫: 'https://www.92wuc.com',
7 | APP下载: 'https://app.clicli.cc',
8 | 使用说明: 'https://www.clicli.cc/play/gv31',
9 | github: 'https://github.com/cliclitv',
10 | 微博: 'https://weibo.com/u/6759984025',
11 | qq群: 'https://jq.qq.com/?_wv=1027&k=5e55m5L',
12 | }
13 | return (
14 |
15 |
16 |
17 | {Object.keys(concat).map((key) => (
18 | {key}
19 | ))}
20 |
21 |
22 | admin@clicli.us © 2020 clicli Proudly use Fre.js, UGC Sponsored by{' '}
23 |
24 |
31 |
32 | .
33 |
34 |
35 |
36 | )
37 | }
38 |
--------------------------------------------------------------------------------
/packages/fre/src/component/footer/index.styl:
--------------------------------------------------------------------------------
1 | .footer
2 | background $bbb
3 | display flex
4 | padding 30px
5 | text-align center
6 | color #888
7 | .links
8 | a
9 | display inline-block
10 | padding 20px
11 | .mail
12 | background $theme
13 | color #fff
14 | border-radius 2px
15 | padding 2px 10px
16 | margin 10px 10px 10px 0
--------------------------------------------------------------------------------
/packages/fre/src/component/header/index.js:
--------------------------------------------------------------------------------
1 | import { h } from 'fre'
2 | import { clink, alink } from 'public/js/const'
3 | import './index.styl'
4 | import Search from 'widget/search'
5 |
6 | export default function Header({ push }) {
7 | const obj = {
8 | 投稿教程: 905,
9 | 使用说明: 31,
10 | 补档: 99
11 | }
12 | return (
13 |
14 |
15 |
16 |
27 |
38 |
39 |
43 |
44 |
45 | )
46 | }
47 |
--------------------------------------------------------------------------------
/packages/fre/src/component/header/index.styl:
--------------------------------------------------------------------------------
1 | header
2 | height 180px
3 | box-shadow $shadow
4 | background url('https://ae01.alicdn.com/kf/U251ceb70165240ef865c7bed275579feN.jpg') center top
5 | background-size auto 100%
6 | .header
7 | position absolute
8 | color #fff
9 | top 0
10 | left 0
11 | right 0
12 | text-shadow 0 1px 1px rgba(0, 0, 0, 0.24)
13 | .nav
14 | padding 20px 0
15 | li
16 | display inline-block
17 | cursor pointer
18 | padding 2px 10px
19 | border-radius 10px
20 | transition 0.3s
21 | li:hover
22 | background $theme
23 | .wrap
24 | display flex
25 | align-items center
26 | .logo
27 | margin 0 10px
28 | width 150px
29 | height 86px
30 | background url('https://p.pstatp.com/origin/ffe900005cf65f21f262')
31 | background-size contain
32 | h1
33 | font-size 14px
34 | display inline-block
35 | padding-bottom 5px
36 | a
37 | color #fff
38 | margin 0 10px
39 | li.active
40 | background $linear
41 | .biu
42 | position absolute
43 | right 0
44 | .login
45 | padding 2px 5px
46 | border-radius 10px
47 | transition 0.3s
48 | background transparent
49 | .login:hover
50 | background $theme
51 | .user-center
52 | background $linear
53 | border-radius 2px
54 | padding 5px 30px
55 | margin-left 10px
56 | .call
57 | background #fff
58 | margin 0 auto
59 | padding 2px 10px
60 | display inline-block
61 | border-radius 10px
62 | color $theme
63 | border 1px solid $theme
64 | margin-left 10px
--------------------------------------------------------------------------------
/packages/fre/src/component/home/index.js:
--------------------------------------------------------------------------------
1 | import { h } from 'fre'
2 | import Header from 'component/header'
3 | import Recommend from 'component/recommend'
4 | import Footer from 'component/footer'
5 | import Rank from 'component/rank'
6 | import WeekList from 'component/week-list'
7 | import UgcList from 'component/ugc-list'
8 | import PostList from 'component/post-list'
9 | import Ad from 'widget/ad'
10 | import './index.styl'
11 | import './m.styl'
12 |
13 | export default function Home({ push }) {
14 | return (
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | )
27 | }
28 |
--------------------------------------------------------------------------------
/packages/fre/src/component/home/index.styl:
--------------------------------------------------------------------------------
1 | *
2 | padding 0
3 | margin 0
4 | body
5 | font 14px '14px -apple-system,BlinkMacSystemFont,Helvetica Neue,Helvetica,Arial,PingFang SC,Hiragino Sans GB,Microsoft YaHei,sans-serif'
6 | color #444
7 | padding 0
8 | margin 0
9 | min-width 1200px
10 | a
11 | text-decoration none
12 | color #444
13 | li
14 | list-style none
15 | input, button
16 | outline none
17 | .wrap
18 | width 1160px
19 | margin 0 auto
20 | position relative
21 | h1
22 | font-size 28px
23 | font-weight normal
24 | padding 30px 0
25 | img
26 | background #f4f6fa
27 | ::-webkit-scrollbar
28 | background #fff
29 | width 5px
30 | ::-webkit-scrollbar-thumb
31 | background $theme
32 | border-radius 2px
33 | ::-webkit-scrollbar-track
34 | background #f4f4fa
35 |
--------------------------------------------------------------------------------
/packages/fre/src/component/home/m.styl:
--------------------------------------------------------------------------------
1 | @media screen and (max-width: 480px)
2 | h1
3 | padding 20px 10px
4 | font-size 24px
5 | .rank, .footer, .biu, .logo, .tab-right
6 | display none
7 | body
8 | min-width 100%
9 | .wrap
10 | width 100%
11 | nav
12 | a
13 | margin 0 !important
14 | .active
15 | margin-left 10px
16 | header
17 | height 120px
18 | .search
19 | transform translate(-50%, 0)
20 | .cover, .cover img
21 | width 100% !important
22 | height 180px !important
23 | box-shadow none !important
24 | .recommend
25 | box-sizing border-box
26 | padding 1px
27 | height 800px
28 | overflow hidden
29 | li
30 | width 33.3%
31 | padding 1px
32 | box-sizing border-box
33 | .title
34 | width 100%
35 | .week-list
36 | padding-bottom 20px
37 | .posts
38 | height auto
39 | padding 0 10px
40 | box-sizing border-box
41 | li
42 | width 25%
43 | h1
44 | display none
45 | .headline
46 | ul
47 | display flex
48 | button
49 | margin 3px !important
50 | .cover, img
51 | height 80px !important
52 | width 80px !important
53 | border-radius 40px !important
54 | .title
55 | height 30px !important
56 | .post-list
57 | box-sizing border-box
58 | padding 1px
59 | li
60 | width 33.3%
61 | margin 0
62 | box-sizing border-box
63 | padding 1px
64 | .title
65 | width 100%
66 | .right
67 | box-sizing border-box
68 | width 100%
69 | .info
70 | width 100%
71 | .video-list
72 | width 100%
73 | box-sizing border-box
74 | .ep
75 | width 100%
76 | height auto
77 | .close
78 | right 50%
79 | transform translate(50%, 0)
80 | top -50px
81 | .ugc-list
82 | padding 5px 5px 20px 5px
83 | li
84 | width 50% !important
85 | margin 0 !important
86 | padding 5px !important
87 | box-sizing border-box
88 | .post
89 | box-shadow none !important
90 | .cover
91 | height 120px !important
92 | img
93 | height 120px !important
--------------------------------------------------------------------------------
/packages/fre/src/component/page/index.js:
--------------------------------------------------------------------------------
1 | import { h } from 'fre'
2 | import Tab from 'widget/tab'
3 | import PostDetal from 'component/post-detail'
4 | import Footer from '../../component/footer'
5 | import {getAv} from '../../public/js/util'
6 | import './index.styl'
7 |
8 | export default function Page(props) {
9 | const gv = props.gv
10 | return
17 | }
--------------------------------------------------------------------------------
/packages/fre/src/component/page/index.styl:
--------------------------------------------------------------------------------
1 | .call
2 | background $theme
3 | color #fff
4 | margin: 0 auto
5 | padding: 2px 50px
6 | display inline-block
7 | border-radius 0 0 2px 2px
8 |
9 | *
10 | padding 0
11 | margin 0
12 |
13 | body, :host
14 | font: 14px '14px -apple-system,BlinkMacSystemFont,Helvetica Neue,Helvetica,Arial,PingFang SC,Hiragino Sans GB,Microsoft YaHei,sans-serif'
15 | color: #444
16 | padding 0
17 | margin 0
18 |
19 | a
20 | text-decoration: none
21 | color: #444444
22 |
23 | li
24 | list-style: none
25 |
26 | input, button
27 | outline: none
28 |
29 | .wrap
30 | width: 1160px
31 | margin: 0 auto
32 | position: relative
33 |
34 |
35 | h1
36 | font-size: 28px
37 | font-weight: normal
38 | padding: 30px 0
39 |
40 | img
41 | background: #f4f6fa
42 |
43 |
44 |
--------------------------------------------------------------------------------
/packages/fre/src/component/post-detail/index.js:
--------------------------------------------------------------------------------
1 | import { h, useRef, useEffect, useState, useLayout } from 'fre'
2 | import './index.styl'
3 | import VideoList from 'component/video-list'
4 | import { getPostDetail, getPv } from '../../api/get'
5 | import { getAvatar } from '../../public/js/util'
6 | import snarkdown from './snarkdown'
7 |
8 | export default function PostDetal(props) {
9 | const t = useRef(null)
10 | const u = useRef(null)
11 | const [post, setPost] = useState({})
12 | const [pv, setPv] = useState(0)
13 | useEffect(() => {
14 | getPostDetail(props.gv).then(res => {
15 | setPost(res.result)
16 | getPv(props.gv).then(ret => {
17 | setPv(ret.result.pv)
18 | })
19 | const w = document.body.clientWidth
20 | if (res.result.tag.indexOf('其它') > -1 || w < 480) {
21 | t.current.style.display = 'none'
22 | u.current.style.display = 'block'
23 | u.current.innerHTML = snarkdown(res.result.content)
24 | } else {
25 | t.current.innerHTML = snarkdown(res.result.content)
26 | }
27 | })
28 | }, [props.gv])
29 |
30 | const videos = post.videos ? post.videos.split('\n').map(v => v.split(' ')).filter(i=>i.length>0) : []
31 |
32 | return (
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
{post.uname}
42 |
uid:{post.uid}
43 |
44 |
45 |
{post.title || '少年祈祷中……'}
46 | {pv} ℃
47 |
48 |
49 | {post.tag}
50 | {post.time}
51 |
52 |
53 |
54 | {post.status === 'public' ?
:
版权原因,该番剧未上架,请支持正版
}
55 |
56 |
57 | )
58 | }
59 |
--------------------------------------------------------------------------------
/packages/fre/src/component/post-detail/index.styl:
--------------------------------------------------------------------------------
1 | .post-detail
2 | width 100%
3 | display flex
4 | .left
5 | width 520px
6 | padding 20px 10px
7 | article
8 | img[alt=suo]
9 | width 100%
10 | border-radius 2px
11 | img
12 | max-width 100%
13 | border-radius 2px
14 | h1
15 | font-size 18px
16 | font-weight bold
17 | padding 0 10px
18 | margin 20px 0
19 | border-left 5px solid $theme
20 | h2
21 | font-size 16px
22 | font-weight bold
23 | padding 0 10px
24 | margin 18px 0
25 | border-left 5px solid $theme
26 | h3
27 | font-size 14px
28 | font-weight bold
29 | padding 0 10px
30 | margin 16px 0
31 | border-left 5px solid $theme
32 | blockquote
33 | word-wrap break-word
34 | background rgba(148, 108, 230, 0.1)
35 | color $theme
36 | padding 10px
37 | margin 10px 0
38 | a
39 | text-decoration none
40 | color $theme
41 | padding 0 5px
42 | font-weight bold
43 | .right
44 | width 600px
45 | padding 10px
46 | margin 20px auto
47 | .info
48 | .user
49 | display flex
50 | align-items center
51 | .avatar, .avatar img
52 | width 60px
53 | height 60px
54 | border-radius 30px
55 | span
56 | padding 10px
57 | .uid
58 | color #bbb
59 | .title
60 | display flex
61 | padding 10px
62 | align-items center
63 | h1
64 | overflow hidden
65 | padding 0
66 | display inline-block
67 | .pv
68 | background $theme
69 | padding 10px 15px !important
70 | border-radius 40px 40px 40px 0
71 | color #fff
72 | font-size 14px
73 | text-align center
74 | margin-left 20px
75 | .copyright
76 | padding 10px
77 | font-size 20px
78 | color #888
79 | .other
80 | padding 20px 0
81 | display none
82 |
--------------------------------------------------------------------------------
/packages/fre/src/component/post-detail/snarkdown.js:
--------------------------------------------------------------------------------
1 | const TAGS = {
2 | _ : ['',''],
3 | '~' : ['',''],
4 | '\n' : ['
'],
5 | ' ' : ['
'],
6 | '-': ['
']
7 | };
8 |
9 | /** Outdent a string based on the first indented line's leading whitespace
10 | * @private
11 | */
12 | function outdent(str) {
13 | return str.replace(RegExp('^'+(str.match(/^(\t| )+/) || '')[0], 'gm'), '');
14 | }
15 |
16 | /** Encode special attribute characters to HTML entities in a String.
17 | * @private
18 | */
19 | function encodeAttr(str) {
20 | return (str+'').replace(/"/g, '"').replace(//g, '>');
21 | }
22 |
23 | /** Parse Markdown into an HTML String. */
24 | export default function parse(md, prevLinks) {
25 | let tokenizer = /((?:^|\n+)(?:\n---+|\* \*(?: \*)+)\n)|(?:^``` *(\w*)\n([\s\S]*?)\n```$)|((?:(?:^|\n+)(?:\t| {2,}).+)+\n*)|((?:(?:^|\n)([>*+-]|\d+\.)\s+.*)+)|(?:\!\[([^\]]*?)\]\(([^\)]+?)\))|(\[)|(\](?:\(([^\)]+?)\))?)|(?:(?:^|\n+)([^\s].*)\n(\-{3,}|={3,})(?:\n+|$))|(?:(?:^|\n+)(#{1,6})\s*(.+)(?:\n+|$))|(?:`([^`].*?)`)|( \n\n*|\n{2,}|__|\*\*|[_*]|~~)/gm,
26 | context = [],
27 | out = '',
28 | links = prevLinks || {},
29 | last = 0,
30 | chunk, prev, token, inner, t;
31 |
32 | function tag(token) {
33 | var desc = TAGS[token.replace(/\*/g,'_')[1] || ''],
34 | end = context[context.length-1]==token;
35 | if (!desc) return token;
36 | if (!desc[1]) return desc[0];
37 | context[end?'pop':'push'](token);
38 | return desc[end|0];
39 | }
40 |
41 | function flush() {
42 | let str = '';
43 | while (context.length) str += tag(context[context.length-1]);
44 | return str;
45 | }
46 |
47 | md = md.replace(/^\[(.+?)\]:\s*(.+)$/gm, (s, name, url) => {
48 | links[name.toLowerCase()] = url;
49 | return '';
50 | }).replace(/^\n+|\n+$/g, '');
51 |
52 | while ( (token=tokenizer.exec(md)) ) {
53 | prev = md.substring(last, token.index);
54 | last = tokenizer.lastIndex;
55 | chunk = token[0];
56 | if (prev.match(/[^\\](\\\\)*\\$/)) {
57 | // escaped
58 | }
59 | // Code/Indent blocks:
60 | else if (token[3] || token[4]) {
61 | chunk = ''+outdent(encodeAttr(token[3] || token[4]).replace(/^\n+|\n+$/g, ''))+'
';
62 | }
63 | // > Quotes, -* lists:
64 | else if (token[6]) {
65 | t = token[6];
66 | if (t.match(/\./)) {
67 | token[5] = token[5].replace(/^\d+/gm, '');
68 | }
69 | console.log(token[5])
70 | inner = parse(outdent(token[5].replace(/^\s*[>*+.-]/gm, '\n')));
71 | if (t==='>') t = 'blockquote';
72 | else {
73 | t = t.match(/\./) ? 'ol' : 'ul';
74 | inner = inner.replace(/^(.*)(\n|$)/gm, '$1');
75 | }
76 | chunk = '<'+t+'>' + inner + ''+t+'>';
77 | }
78 | // Images:
79 | else if (token[8]) {
80 | chunk = `
`;
81 | }
82 | // Links:
83 | else if (token[10]) {
84 | out = out.replace('', ``);
85 | chunk = flush() + '';
86 | }
87 | else if (token[9]) {
88 | chunk = '';
89 | }
90 | // Headings:
91 | else if (token[12] || token[14]) {
92 | t = 'h' + (token[14] ? token[14].length : (token[13][0]==='='?1:2));
93 | chunk = '<'+t+'>' + parse(token[12] || token[15], links) + ''+t+'>';
94 | }
95 | // `code`:
96 | else if (token[16]) {
97 | chunk = ''+encodeAttr(token[16])+'
';
98 | }
99 | // Inline formatting: *em*, **strong** & friends
100 | else if (token[17] || token[1]) {
101 | chunk = tag(token[17] || '--');
102 | }
103 | out += prev;
104 | out += chunk;
105 | }
106 |
107 | return (out + md.substring(last) + flush()).trim();
108 | }
--------------------------------------------------------------------------------
/packages/fre/src/component/post-list/index.js:
--------------------------------------------------------------------------------
1 | import { h, useEffect, useState } from 'fre'
2 | import { getPost } from 'api/get'
3 | import { getSuo } from 'public/js/util'
4 | import { clink } from 'public/js/const'
5 | import './index.styl'
6 |
7 | export default function PostList(props) {
8 | const [posts, setPosts] = useState([])
9 | useEffect(() => {
10 | getPost('bgm', '', 1, 30).then(res => {
11 | setPosts(res.posts)
12 | })
13 | }, [])
14 | return (
15 |
16 |
最新更新
17 |
18 | {posts.length > 0 &&
19 | posts.map(item => {
20 | return (
21 | - props.push(`/play/gv${item.id}`)}>
22 |
23 |
})
24 |
25 | {item.title}
26 |
27 | )
28 | })}
29 |
30 |
31 | )
32 | }
33 |
--------------------------------------------------------------------------------
/packages/fre/src/component/post-list/index.styl:
--------------------------------------------------------------------------------
1 | .post-list
2 | margin-bottom 30px!important
3 | li
4 | width 176.6px
5 | display inline-block
6 | margin-right 20px
7 | box-sizing border-box
8 | cursor: pointer
9 | .title
10 | width 170px
11 | height 40px
12 | overflow hidden
13 | padding: 10px 0
14 | .cover,.cover img
15 | width 100%
16 | height 230px
17 | box-shadow $shadow
18 | border-radius 2px
19 | object-fit cover
20 |
21 | li:nth-child(6n)
22 | margin-right 0
--------------------------------------------------------------------------------
/packages/fre/src/component/rank/index.js:
--------------------------------------------------------------------------------
1 | import { h, useEffect, useState } from 'fre'
2 | import { getRank } from 'api/get'
3 | import { getSuo } from 'public/js/util'
4 | import './index.styl'
5 | import { clink } from 'public/js/const'
6 | export default function Rank(props) {
7 | const [posts, setPosts] = useState([])
8 | useEffect(() => {
9 | getRank().then(res => {
10 | setPosts(res.posts)
11 | })
12 | }, [])
13 | return (
14 |
15 |
排行榜
16 |
17 | {posts.length > 0 &&
18 | posts.map((item, index) => {
19 | return index === 0 ? (
20 | - props.push(`/play/gv${item.id}`)} className='current' key={item.id}>
21 |
22 |
})
23 |
24 |
25 |
{item.title}
26 |
27 |
{item.tag}
28 |
{index + 1}
29 |
30 |
31 |
32 | ) : (
33 | - props.push(`/play/gv${item.id}`)} key={item.id}>
34 | {index + 1}
35 |
36 | {item.title}
37 |
38 |
39 | )
40 | })}
41 |
42 |
43 | )
44 | }
45 |
--------------------------------------------------------------------------------
/packages/fre/src/component/rank/index.styl:
--------------------------------------------------------------------------------
1 | .rank
2 | width 310px
3 | .title
4 | padding: 0 10px
5 | height 21px
6 | overflow hidden
7 | .cover,.cover img
8 | width 150px
9 | height 210px
10 | box-shadow $shadow
11 | border-radius 2px
12 | object-fit cover
13 | .current
14 | display flex
15 | position relative
16 | padding 0 7px 14px 7px
17 | .title
18 | font-size: 16px
19 | transition: 0.3s
20 | .bom
21 | position absolute
22 | display flex
23 | align-items baseline
24 | bottom 12px
25 | .tag
26 | font-size: 12px
27 | padding 0 10px
28 | color: $grey
29 | .idx
30 | font-size: 60px
31 | color: $theme
32 | font-weight: bold
33 | position: relative
34 | bottom: -18px
35 | .current:hover
36 | .title
37 | color $theme
38 | li
39 | display flex
40 | padding: 7px
41 | cursor pointer
42 | span
43 | font-size:16px
44 | font-weight bold
45 | color: $grey
46 | .active
47 | color: $theme
48 | a,.info
49 | width: 0
50 | flex-grow: 1
51 | .title
52 | transition 0.3s
53 | overflow hidden
54 | text-overflow ellipsis
55 | white-space nowrap
56 | li:hover
57 | .title
58 | color: $theme
59 |
--------------------------------------------------------------------------------
/packages/fre/src/component/recommend/index.js:
--------------------------------------------------------------------------------
1 | import {h, useEffect, useState} from 'fre'
2 | import {getPost} from 'api/get'
3 | import {getSuo} from 'public/js/util'
4 | import {clink} from 'public/js/const'
5 | import './index.styl'
6 |
7 | export default function Recommend(props) {
8 | const [posts, setPosts] = useState([])
9 | useEffect(() => {
10 | getPost('', '推荐', 1, 10).then(res => {
11 | setPosts(res.posts)
12 | })
13 | }, [])
14 | return
15 |
编辑推荐
16 |
17 | {posts.length > 0 && posts.map(item => {
18 | return - props.push(`/play/gv${item.id}`)} key={item.id} >
19 |
20 |
}/)
21 |
22 | {item.title}
23 |
24 | })}
25 |
26 |
27 | }
--------------------------------------------------------------------------------
/packages/fre/src/component/recommend/index.styl:
--------------------------------------------------------------------------------
1 | .recommend
2 | width 850px
3 | li
4 | width 20%
5 | display inline-block
6 | cursor: pointer
7 | .title
8 | width 150px
9 | height 40px
10 | overflow hidden
11 | margin: 10px 0
12 | .cover,.cover img
13 | width 150px
14 | height 210px
15 | box-shadow $shadow
16 | border-radius 2px
17 | object-fit cover
--------------------------------------------------------------------------------
/packages/fre/src/component/search/index.js:
--------------------------------------------------------------------------------
1 | import { h } from 'fre'
2 | import Tab from 'widget/tab'
3 | import Footer from 'component/footer'
4 | import UgcList from 'component/ugc-list'
5 |
6 | export default function List(props) {
7 | return (
8 |
9 |
10 |
11 |
12 |
13 | )
14 | }
15 |
--------------------------------------------------------------------------------
/packages/fre/src/component/search/index.styl:
--------------------------------------------------------------------------------
1 | .call
2 | background $theme
3 | color #fff
4 | margin: 0 auto
5 | padding: 2px 50px
6 | display inline-block
7 | border-radius 0 0 2px 2px
8 |
9 | *
10 | padding 0
11 | margin 0
12 |
13 | body, :host
14 | font: 14px '14px -apple-system,BlinkMacSystemFont,Helvetica Neue,Helvetica,Arial,PingFang SC,Hiragino Sans GB,Microsoft YaHei,sans-serif'
15 | color: #444
16 | padding 0
17 | margin 0
18 |
19 | a
20 | text-decoration: none
21 | color: #444444
22 |
23 | li
24 | list-style: none
25 |
26 | input, button
27 | outline: none
28 |
29 | .wrap
30 | width: 1160px
31 | margin: 0 auto
32 | position: relative
33 |
34 |
35 | h1
36 | font-size: 28px
37 | font-weight: normal
38 | padding: 30px 0
39 |
40 | img
41 | background: #f4f6fa
42 |
43 |
44 |
--------------------------------------------------------------------------------
/packages/fre/src/component/ugc-list/index.js:
--------------------------------------------------------------------------------
1 | import { h, useEffect, useState } from 'fre'
2 | import { getPost, getSearch } from 'api/get'
3 | import { getAvatar, getSuo } from 'public/js/util'
4 | import './index.styl'
5 | import { clink } from 'public/js/const'
6 |
7 | export default function UGCList(props) {
8 | const [posts, setPosts] = useState([])
9 | useEffect(() => {
10 | if (props.word) {
11 | getSearch(props.word).then(res => setPosts(res.posts))
12 | } else {
13 | getPost('原创', '', 2, 4).then(res => setPosts(res.posts))
14 | }
15 | }, [])
16 | return (
17 |
18 |
19 |
{props.title}
20 |
21 | {posts &&
22 | posts.map(item => (
23 | - props.push(`/play/gv${item.id}`)} key={item.id}>
24 |
25 |
26 |
})
27 |
28 |
29 |
30 |
})
31 |
32 |
{item.title}
33 |
34 |
35 |
36 | ))}
37 |
38 |
39 |
40 | )
41 | }
42 |
--------------------------------------------------------------------------------
/packages/fre/src/component/ugc-list/index.styl:
--------------------------------------------------------------------------------
1 | .ugc-list
2 | background $bbb
3 | padding-bottom 50px
4 | .posts
5 | li
6 | display inline-block
7 | width 275px
8 | text-align center
9 | margin-right: 20px
10 | margin-bottom: 20px
11 | .post
12 | background #fff
13 | border-radius 2px
14 | box-shadow $shadow
15 | .cover, .cover img
16 | height 160px
17 | width 100%
18 | object-fit cover
19 | .title
20 | overflow hidden
21 | padding-left 10px
22 | height 18px
23 | .info
24 | display flex
25 | padding 10px
26 | align-items center
27 | .uqq, .uqq img
28 | height 40px
29 | width 40px
30 | border-radius 50%
31 | li:nth-child(4n)
32 | margin-right 0!important
--------------------------------------------------------------------------------
/packages/fre/src/component/video-list/index.js:
--------------------------------------------------------------------------------
1 | import { h, useState, useEffect, useRef } from 'fre'
2 | import Eplayer from '../../widget/eplayer'
3 |
4 | import './index.styl'
5 |
6 | export default function VideoList(props) {
7 | const [content, setContent] = useState(null)
8 |
9 | function hide() {
10 | setContent(null)
11 | document.body.style.overflow = 'auto'
12 | }
13 |
14 | function show(url) {
15 | setContent(url)
16 | document.body.style.overflow = 'hidden'
17 | }
18 | return (
19 |
20 | {props.videos.length < 27
21 | ? props.videos.map((item,index) => {
22 | return (
23 |
show(item[1])}>
24 | P {index}
25 | {item[0]}
26 |
27 | )
28 | })
29 | : props.videos.map((item,index)=>{
30 | return show(item[1])}>P {index}
31 | })}
32 | {content && }
33 |
34 | )
35 | }
36 |
--------------------------------------------------------------------------------
/packages/fre/src/component/video-list/index.styl:
--------------------------------------------------------------------------------
1 | .video-list
2 | width 600px
3 | float left
4 | padding 10px 0
5 | .item
6 | display flex
7 | align-items center
8 | padding 10px
9 | cursor pointer
10 | img
11 | width 40px
12 | height 40px
13 | border-radius 50%
14 | margin 6px 10px
15 | span
16 | padding 10px
17 | .item:nth-of-type(even)
18 | background #f4f6fa
19 | .item2
20 | display inline-block
21 | background: #f4f6fa
22 | padding: 10px
23 | border-radius: 2px
24 | margin: 10px
25 | cursor pointer
--------------------------------------------------------------------------------
/packages/fre/src/component/week-list/index.js:
--------------------------------------------------------------------------------
1 | import { h, useEffect, useState } from 'fre'
2 | import { getPost } from 'api/get'
3 | import { getSuo } from 'public/js/util'
4 | import './index.styl'
5 |
6 | export default function WeekList({ push }) {
7 | const [posts, setPosts] = useState([])
8 | const [day, setDay] = useState(new Date().getDay())
9 | useEffect(() => {
10 | getPost('新番', '', 1, 100, 'nowait').then(res => {
11 | let ret = {}
12 | res.posts.forEach(item => {
13 | let day = new Date(item.time).getDay()
14 | ret[day] = ret[day] || []
15 | ret[day].push(item)
16 | })
17 | setPosts(ret)
18 | })
19 | }, [])
20 | const map = {
21 | 0: '周日',
22 | 1: '周一',
23 | 2: '周二',
24 | 3: '周三',
25 | 4: '周四',
26 | 5: '周五',
27 | 6: '周六'
28 | }
29 | return (
30 |
31 |
32 |
33 |
更新表
34 |
35 | {map &&
36 | Object.keys(map).map((item, index) => (
37 |
40 | ))}
41 |
42 |
43 |
44 | {posts[day] &&
45 | posts[day].map(item => (
46 | - push(`/play/gv${item.id}`)} key={item.id}>
47 |
48 |
49 |
})
50 |
51 |
{item.title}
52 |
53 |
54 | ))}
55 |
56 |
57 |
58 | )
59 | }
60 |
--------------------------------------------------------------------------------
/packages/fre/src/component/week-list/index.styl:
--------------------------------------------------------------------------------
1 | .week-list
2 | .headline
3 | display flex
4 | align-items center
5 | ul
6 | button
7 | background none
8 | border 0
9 | margin: 10px
10 | font-size 16px
11 | padding: 5px
12 | .active
13 | color: $theme
14 | position relative
15 | .active:after
16 | content ""
17 | position absolute
18 | height 3px
19 | width: 10px
20 | background $theme
21 | bottom: 0
22 | left: 50%
23 | transform: translateX(-50%)
24 | button:active
25 | transform: scale(.97)
26 | .posts
27 | height 407px
28 | overflow: auto
29 | li
30 | display inline-block
31 | width 20%
32 | text-align center
33 | cursor: pointer
34 | .post
35 | padding-right: 20px
36 | .cover,img
37 | height 140px
38 | width 100%
39 | object-fit cover
40 | box-shadow $shadow
41 | border-radius 2px
42 | .title
43 | height 40px
44 | overflow hidden
45 | padding: 10px 0
46 |
--------------------------------------------------------------------------------
/packages/fre/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | c站-clicli弹幕网_(⁄•⁄ω⁄•⁄) 社保~ clicli.cc
8 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/packages/fre/src/index.js:
--------------------------------------------------------------------------------
1 | import { h, render, useEffect } from 'fre'
2 | import { useLocation } from './use-location'
3 | import Page from 'component/page'
4 | import Home from 'component/home'
5 | import Search from 'component/search'
6 |
7 | const App = () => {
8 | const [location, setLocation] = useLocation()
9 | const p = location.match(/gv(\S*)+/)
10 | const s = location.match(/search\/(\S*)+/)
11 | if (location === '/') {
12 | return
13 | } else if (p) {
14 | return
15 | } else if (s) {
16 | return
17 | } else {
18 | return 404
19 | }
20 | }
21 | // @ts-ignore
22 | const root = document.getElementById('root')
23 | render(, root)
24 |
25 | // if (new Date().getTime() < new Date('2020-04-04').setHours(23, 59, 59, 999)) root.style = 'filter:grayscale(100%)'
26 |
--------------------------------------------------------------------------------
/packages/fre/src/public/css/var.styl:
--------------------------------------------------------------------------------
1 | $theme = #946ce6
2 | $bg = #001935
3 | $grey = #888
4 | $bbb = #f4f6fa
5 | $shadow = 2px 2px 0px rgba(5,20,50,.1)
6 | $linear = linear-gradient(90deg,#946ce6,#7e5fd9)
7 |
--------------------------------------------------------------------------------
/packages/fre/src/public/img/sliders/0.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cliclitv/fre-clicli/a60d1f6b647c5da69f29e046cee52d68adf1b072/packages/fre/src/public/img/sliders/0.jpg
--------------------------------------------------------------------------------
/packages/fre/src/public/img/sliders/1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cliclitv/fre-clicli/a60d1f6b647c5da69f29e046cee52d68adf1b072/packages/fre/src/public/img/sliders/1.jpg
--------------------------------------------------------------------------------
/packages/fre/src/public/img/sliders/2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cliclitv/fre-clicli/a60d1f6b647c5da69f29e046cee52d68adf1b072/packages/fre/src/public/img/sliders/2.jpg
--------------------------------------------------------------------------------
/packages/fre/src/public/img/sliders/3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cliclitv/fre-clicli/a60d1f6b647c5da69f29e046cee52d68adf1b072/packages/fre/src/public/img/sliders/3.jpg
--------------------------------------------------------------------------------
/packages/fre/src/public/js/const.js:
--------------------------------------------------------------------------------
1 | export const clink = 'https://www.clicli.cc'
2 | export const alink = 'https://admin.clicli.cc'
3 | export const isDev = process.env.NODE_ENV === 'development'
--------------------------------------------------------------------------------
/packages/fre/src/public/js/fetch.js:
--------------------------------------------------------------------------------
1 | export function get(url) {
2 | return new Promise((resolve,reject) => {
3 | fetch(url)
4 | .then(res => res.json())
5 | .then(data => {
6 | resolve(data)
7 | }).catch(e=>{
8 | reject(e)
9 | })
10 | })
11 | }
--------------------------------------------------------------------------------
/packages/fre/src/public/js/util.js:
--------------------------------------------------------------------------------
1 | import md5 from 'blueimp-md5'
2 |
3 | export function getAvatar(avatar) {
4 | if (/^[0-9]+$/.test(avatar)) {
5 | return `http://q1.qlogo.cn/g?b=qq&nk=${avatar}&s=640`
6 | } else {
7 | let hash = md5(avatar)
8 | return `https://sdn.geekzu.org/avatar/${hash}?s=100&d=retro`
9 | }
10 | }
11 |
12 | export function getSuo(content) {
13 | let m = content.match(/suo(.+?)\)/i)
14 | return m ? m[1].slice(2) : 'https://wx4.sinaimg.cn/mw690/0060lm7Tly1fvmtrka9p5j30b40b43yo.jpg'
15 | }
16 |
17 | export function getAv(id) {
18 | return id.substring(2, id.length)
19 | }
--------------------------------------------------------------------------------
/packages/fre/src/use-location.js:
--------------------------------------------------------------------------------
1 | import { useEffect, useRef, useState } from 'fre'
2 | // wouter's implement for fre https://github.com/molefrog/wouter/blob/master/use-location.js
3 |
4 | export const useLocation = ({ base = '' } = {}) => {
5 | const [path, update] = useState(currentPathname(base))
6 | const prevPath = useRef(path)
7 |
8 | useEffect(() => {
9 | patchHistoryEvents()
10 | const checkForUpdates = () => {
11 | const pathname = currentPathname(base)
12 | prevPath.current !== pathname && update((prevPath.current = pathname))
13 | }
14 |
15 | const events = ['popstate', 'pushState', 'replaceState']
16 | events.map(e => addEventListener(e, checkForUpdates))
17 | checkForUpdates()
18 |
19 | return () => events.map(e => removeEventListener(e, checkForUpdates))
20 | }, [])
21 | const navigate = (to, replace) =>
22 | history[replace ? 'replaceState' : 'pushState'](0, 0, base + to)
23 | return [path, navigate]
24 | }
25 |
26 | let patched = 0
27 |
28 | const patchHistoryEvents = () => {
29 | if (patched) return
30 | ['pushState', 'replaceState'].map(type => {
31 | const original = history[type]
32 |
33 | history[type] = function() {
34 | const result = original.apply(this, arguments)
35 | const event = new Event(type)
36 | event.arguments = arguments
37 |
38 | dispatchEvent(event)
39 | return result
40 | }
41 | })
42 |
43 | return (patched = 1)
44 | }
45 |
46 | const currentPathname = (base, path = location.pathname) =>
47 | !path.indexOf(base) ? path.slice(base.length) || '/' : path
48 |
--------------------------------------------------------------------------------
/packages/fre/src/widget/ad/index.js:
--------------------------------------------------------------------------------
1 | import { h } from 'fre'
2 |
3 | export default function Ad(props) {
4 | return (
5 |
13 | )
14 | }
15 |
--------------------------------------------------------------------------------
/packages/fre/src/widget/eplayer/index.js:
--------------------------------------------------------------------------------
1 | import { h, useEffect, useRef } from 'fre'
2 | import { getPlayUrl } from '../../api/get'
3 | import './index.styl'
4 |
5 | export default function Eplayer(props) {
6 | const t = useRef(null)
7 | const s = useRef(null)
8 | const isMobile = document.body.clientWidth < 480
9 | const steam = (type, url) => {
10 | switch (type) {
11 | case 'm3u8':
12 | if (Hls.isSupported()) {
13 | let hls = new Hls()
14 | hls.loadSource(url)
15 | hls.attachMedia(s.current)
16 | }
17 | break
18 | default:
19 | s.current.src = url
20 | }
21 | }
22 | useEffect(() => {
23 | getPlayUrl(props.url).then(res => {
24 | if (isMobile) {
25 | steam(res.result.mtype, res.result.url)
26 | s.current.load()
27 | } else {
28 | const type = res.result.mtype === "m3u8" ? "hls" : res.result.mtype
29 | t.current.setAttribute('type', type)
30 | t.current.setAttribute('src', res.result.url)
31 | }
32 | })
33 | }, [props.url])
34 |
35 | return (
36 |
37 |
38 | {isMobile ?
:
}
39 |
40 |
41 |
42 |
43 |
44 |
45 | )
46 | }
47 |
--------------------------------------------------------------------------------
/packages/fre/src/widget/eplayer/index.styl:
--------------------------------------------------------------------------------
1 | .ep
2 | position relative
3 | .mark
4 | background rgba(0, 0, 0, 0.8)
5 | position fixed
6 | top 0
7 | bottom 0
8 | right 0
9 | left 0
10 | .ep
11 | width 800px
12 | height 450px
13 | position fixed
14 | top 50%
15 | left 50%
16 | transform translate(-50%, -50%)
17 | z-index 1
18 | .close
19 | position absolute
20 | top 0
21 | right -50px
22 | z-index 1
23 | color #fff
24 | cursor pointer
25 | padding 10px
26 | .icon-close
27 | font-size 24px
28 | video
29 | width 100%
30 | height 100%
--------------------------------------------------------------------------------
/packages/fre/src/widget/search/index.js:
--------------------------------------------------------------------------------
1 | import { h, useState, useEffect } from 'fre'
2 | import { clink } from 'public/js/const'
3 | import './index.styl'
4 |
5 | export default function Search({ push }) {
6 | const [word, setWord] = useState('')
7 | useEffect(() => {
8 | document.onkeydown = e => {
9 | if (e.keyCode == 13 && word) {
10 | push(`/search/${word}`)
11 | }
12 | }
13 | })
14 | const inputWord = e => {
15 | setWord(e.target.value)
16 | }
17 | return (
18 |
19 |
20 | push(`/search/${word}`)}>
21 |
22 |
23 |
24 | )
25 | }
26 |
--------------------------------------------------------------------------------
/packages/fre/src/widget/search/index.styl:
--------------------------------------------------------------------------------
1 | .search
2 | position absolute
3 | top 50%
4 | left 50%
5 | transform translate(-50%, -70%)
6 | input
7 | padding 10px 15px
8 | border-radius 22px
9 | border 3px solid $theme
10 | background #fff
11 | width 300px
12 | span
13 | position absolute
14 | right 10px
15 | top: 8px
16 | .icon-search
17 | font-size: 24px
18 | font-weight: bold
19 | color: $theme
--------------------------------------------------------------------------------
/packages/fre/src/widget/tab/index.js:
--------------------------------------------------------------------------------
1 | import { h } from 'fre'
2 | import './index.styl'
3 | import { clink } from 'public/js/const'
4 |
5 | export default function Tab() {
6 | const obj = {
7 | 投稿教程: 905,
8 | 使用说明: 31,
9 | 补档: 99
10 | }
11 | return (
12 |
32 | )
33 | }
34 |
--------------------------------------------------------------------------------
/packages/fre/src/widget/tab/index.styl:
--------------------------------------------------------------------------------
1 | .tab
2 | background $theme
3 | height auto
4 | li
5 | display inline-block
6 | padding 20px
7 | cursor: pointer
8 | color #fff
9 | border-top 3px solid $theme
10 | li:hover
11 | border-top-color #fff
12 | .active
13 | border-top-color #fff!important
14 | .tab-right
15 | float right
--------------------------------------------------------------------------------
/packages/fre/src/widget/tag/index.js:
--------------------------------------------------------------------------------
1 | import { h } from 'fre'
2 | import './index.styl'
3 |
4 |
5 | export default function Tag () {
6 | const arr = [
7 | '耽美',
8 | '乙女',
9 | '百合',
10 | '后宫',
11 | '热血',
12 | '运动',
13 | '冒险',
14 | '战斗',
15 | 'r15',
16 | '治愈',
17 | '推理',
18 | '特摄'
19 | ]
20 | return (
21 |
29 | )
30 | }
31 |
--------------------------------------------------------------------------------
/packages/fre/src/widget/tag/index.styl:
--------------------------------------------------------------------------------
1 | .tags
2 | background $bg
3 | padding 10px
4 | .wrap
5 | display flex
6 | a
7 | color #fff
8 | display inline-block
9 | padding 10px 0
10 | flex 1
--------------------------------------------------------------------------------
/packages/fre/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 | const HtmlWebpackPlugin = require('html-webpack-plugin')
3 | const MiniCssExtractPlugin = require('mini-css-extract-plugin')
4 | const { CleanWebpackPlugin } = require('clean-webpack-plugin')
5 |
6 | module.exports = {
7 | entry: './src/index.js',
8 | output: {
9 | path: path.resolve(__dirname, 'dist'),
10 | filename: '[name].js',
11 | publicPath: '/'
12 | },
13 | resolve: {
14 | alias: {
15 | component: path.resolve(__dirname, 'src/component'),
16 | public: path.resolve(__dirname, 'src/public'),
17 | api: path.resolve(__dirname, 'src/api'),
18 | widget: path.resolve(__dirname, 'src/widget')
19 | }
20 | },
21 | module: {
22 | rules: [
23 | {
24 | test: /\.js$/,
25 | use: {
26 | loader: 'babel-loader'
27 | }
28 | },
29 | {
30 | test: /\.styl$/,
31 | use: [MiniCssExtractPlugin.loader, 'css-loader', {
32 | loader: 'stylus-loader',
33 | options: {
34 | import: [path.resolve(__dirname, 'src/public/css/var.styl')]
35 | }
36 | }]
37 | },
38 | {
39 | test: /\.css$/,
40 | use: [MiniCssExtractPlugin.loader, 'css-loader']
41 | }
42 | ]
43 | },
44 | optimization: {
45 | splitChunks: {
46 | chunks: 'all'
47 | }
48 | },
49 | plugins: [
50 | new HtmlWebpackPlugin({
51 | template: './src/index.html'
52 | }),
53 | new CleanWebpackPlugin({
54 | cleanOnceBeforeBuildPatterns: ['*/**', '!CNAME']
55 | }),
56 |
57 | new MiniCssExtractPlugin({
58 | filename: '[name].css',
59 | })
60 | ],
61 | devServer: {
62 | headers: { 'Access-Control-Allow-Origin': '*' },
63 | contentBase: path.join(__dirname, 'dist'),
64 | compress: true,
65 | port: 8080,
66 | historyApiFallback: true,
67 | hot: true
68 | }
69 | }
--------------------------------------------------------------------------------
/packages/react/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "@babel/preset-env",
4 | "@babel/preset-react"
5 | ],
6 | "plugins": [
7 | [
8 | "@babel/plugin-proposal-decorators",
9 | {
10 | "legacy": true
11 | }
12 | ],
13 | "@babel/plugin-syntax-dynamic-import",
14 | "@babel/plugin-transform-runtime"
15 | ]
16 | }
--------------------------------------------------------------------------------
/packages/react/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | .idea/
3 | yarn-error.log
4 |
5 |
--------------------------------------------------------------------------------
/packages/react/README.md:
--------------------------------------------------------------------------------
1 |
2 | # emmm
--------------------------------------------------------------------------------
/packages/react/dist/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | clicli后台
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/packages/react/dist/runtime~main.js:
--------------------------------------------------------------------------------
1 | !function(e){function r(r){for(var t,o,i=r[0],c=r[1],d=r[2],a=0,l=[];a=0&&n._disposeHandlers.splice(r,1)},invalidate:function(){switch(this._selfInvalidated=!0,u){case"idle":(v={})[r]=e[r],f("ready");break;case"ready":I(r);break;case"prepare":case"check":case"dispose":case"apply":(b=b||[]).push(r)}},check:D,apply:x,status:function(e){if(!e)return u;p.push(e)},addStatusHandler:function(e){p.push(e)},removeStatusHandler:function(e){var r=p.indexOf(e);r>=0&&p.splice(r,1)},data:d[r]};return o=void 0,n}var p=[],u="idle";function f(e){u=e;for(var r=0;r0;){var o=t.pop(),i=o.id,c=o.chain;if((s=k[i])&&(!s.hot._selfAccepted||s.hot._selfInvalidated)){if(s.hot._selfDeclined)return{type:"self-declined",chain:c,moduleId:i};if(s.hot._main)return{type:"unaccepted",chain:c,moduleId:i};for(var d=0;d ")),E.type){case"self-declined":n.onDeclined&&n.onDeclined(E),n.ignoreDeclined||(P=new Error("Aborted because of self decline: "+E.moduleId+A));break;case"declined":n.onDeclined&&n.onDeclined(E),n.ignoreDeclined||(P=new Error("Aborted because of declined dependency: "+E.moduleId+" in "+E.parentId+A));break;case"unaccepted":n.onUnaccepted&&n.onUnaccepted(E),n.ignoreUnaccepted||(P=new Error("Aborted because "+p+" is not accepted"+A));break;case"accepted":n.onAccepted&&n.onAccepted(E),x=!0;break;case"disposed":n.onDisposed&&n.onDisposed(E),I=!0;break;default:throw new Error("Unexception type "+E.type)}if(P)return f("abort"),Promise.reject(P);if(x)for(p in m[p]=v[p],h(O,E.outdatedModules),E.outdatedDependencies)Object.prototype.hasOwnProperty.call(E.outdatedDependencies,p)&&(w[p]||(w[p]=[]),h(w[p],E.outdatedDependencies[p]));I&&(h(O,[E.moduleId]),m[p]=g)}var U,q=[];for(i=0;i0;)if(p=J.pop(),s=k[p]){var L={},N=s.hot._disposeHandlers;for(l=0;l=0&&X.parents.splice(U,1))}}for(p in w)if(Object.prototype.hasOwnProperty.call(w,p)&&(s=k[p]))for(T=w[p],l=0;l=0&&s.children.splice(U,1);f("apply"),void 0!==y&&(c=y,y=void 0);for(p in v=void 0,m)Object.prototype.hasOwnProperty.call(m,p)&&(e[p]=m[p]);var C=null;for(p in w)if(Object.prototype.hasOwnProperty.call(w,p)&&(s=k[p])){T=w[p];var G=[];for(i=0;i",
7 | "license": "MIT",
8 | "scripts": {
9 | "build": "cross-env NODE_ENV=production webpack --mode production",
10 | "start": "cross-env NODE_ENV=development webpack-dev-server --mode development"
11 | },
12 | "dependencies": {
13 | "axios": "^0.21.2",
14 | "blueimp-md5": "^2.10.0",
15 | "js-base64": "^2.4.9",
16 | "js-cookie": "^2.2.0",
17 | "react": "^16.5.2",
18 | "react-dom": "^16.5.2",
19 | "react-loadable": "^5.5.0",
20 | "react-router-dom": "^4.3.1",
21 | "simplemde": "^1.11.2",
22 | "smox": "^1.3.3"
23 | },
24 | "devDependencies": {
25 | "@babel/core": "^7.1.0",
26 | "@babel/plugin-proposal-decorators": "^7.1.0",
27 | "@babel/plugin-syntax-dynamic-import": "^7.0.0",
28 | "@babel/plugin-transform-runtime": "^7.2.0",
29 | "@babel/preset-env": "^7.1.0",
30 | "@babel/preset-react": "^7.0.0",
31 | "@babel/runtime": "^7.3.1",
32 | "babel-loader": "^8.0.2",
33 | "cross-env": "^5.2.0",
34 | "css-loader": "^1.0.0",
35 | "file-loader": "^2.0.0",
36 | "html-webpack-plugin": "^3.2.0",
37 | "mini-css-extract-plugin": "^0.4.3",
38 | "style-loader": "^0.23.0",
39 | "url-loader": "^1.1.1",
40 | "webpack": "^4.20.2",
41 | "webpack-cli": "^3.1.1",
42 | "webpack-dev-server": "^3.1.9"
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/packages/react/src/api/comment.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios'
2 | import {isDev, API_LINK} from 'common/js/util'
3 |
4 |
5 | // 根据pid查找评论
6 | export function getCommentByPid(pid, page, pageSize) {
7 | return request.get('/comments', {
8 | params: {pid, page, pageSize}
9 | })
10 | }
11 |
12 | // 根据 uid 查找评论
13 | export function getCommentByUid(uid, page, pageSize) {
14 | return request.get('/comments', {
15 | params: {uid, page, pageSize}
16 | })
17 | }
18 |
19 |
20 | // 根据pid删除评论
21 | export function deleteCommentByPid(pid) {
22 | return axios.post(`/comment/delete?pid=${pid}`)
23 | }
--------------------------------------------------------------------------------
/packages/react/src/api/jx.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios'
2 |
3 | export function getHcyList(fid) {
4 | return axios.get('/hcy/list', {
5 | params: {
6 | fid
7 | }
8 | })
9 |
10 | }
--------------------------------------------------------------------------------
/packages/react/src/api/post.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios'
2 | import {isDev, API_LINK} from 'common/js/util'
3 | import Cookies from 'js-cookie'
4 |
5 | axios.defaults.withCredentials = true
6 |
7 | export function getPosts(status, sort, tag, uid, page, pageSize) {
8 | return axios.get(`//api.clicli.cc/posts`, {
9 | params: {
10 | status, sort, tag, uid, page, pageSize
11 | }
12 | })
13 | }
14 |
15 | export function getPost(id) {
16 | return axios.get(`//api.clicli.cc/post/${id}`)
17 | }
18 |
19 | export function add({title, content, status, sort, tag, uid, videos}) {
20 | return axios.post('//api.clicli.cc/post/add', {
21 | title,
22 | content,
23 | status,
24 | sort,
25 | tag,
26 | uid,
27 | videos
28 | }, {
29 | headers: {
30 | 'token': Cookies.get('token')
31 | }
32 | })
33 | }
34 |
35 | // 更新文章
36 | export function update({id, title, content, status, sort, tag, uid, time,videos}) {
37 | return axios.post(`//api.clicli.cc/post/update/${id}`, {
38 | title,
39 | content,
40 | status,
41 | sort,
42 | tag,
43 | uid,
44 | time,
45 | videos
46 | }, {
47 | headers: {
48 | 'token': Cookies.get('token')
49 | }
50 | })
51 | }
52 |
53 | // 删除一篇文章
54 | export function deletePost(id) {
55 | return axios.post(`//api.clicli.cc/post/delete/${id}`, {}, {
56 | headers: {
57 | 'token': Cookies.get('token')
58 | }
59 | })
60 | }
61 |
62 |
--------------------------------------------------------------------------------
/packages/react/src/api/user.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios'
2 | import Cookies from "js-cookie"
3 |
4 | axios.defaults.withCredentials = true
5 |
6 | // 用户登录
7 | export function login(user) {
8 | return axios.post('//api.clicli.cc/user/login', {
9 | name: user.name,
10 | pwd: user.pwd
11 | })
12 | }
13 |
14 |
15 | // 用户注册
16 | export function register(user) {
17 | return axios.post('//api.clicli.cc/user/register', {
18 | name: user.name,
19 | pwd: user.pwd,
20 | qq: user.qq,
21 | level: 1,
22 | desc: '人懒,竟然没有签名~'
23 | })
24 | }
25 |
26 | // 更新用户信息
27 | export function update(user) {
28 | return axios.post(`//api.clicli.cc/user/update/${user.id}`, {
29 | name: user.name,
30 | pwd: user.pwd,
31 | qq: user.qq,
32 | level: parseInt(user.level),
33 | desc: user.desc
34 | }, {
35 | headers: {
36 | 'token': Cookies.get('token')
37 | }
38 | })
39 | }
40 |
41 | // 获取用户列表
42 | export function userList(level) {
43 | return axios.get('//api.clicli.cc/users', {
44 | params: {
45 | level,
46 | page: 1,
47 | pageSize: 100
48 | }
49 | })
50 | }
51 |
52 |
53 | // 用户退出
54 | export function logout() {
55 | return axios.post('//api.clicli.cc/user/logout')
56 | }
57 |
58 | // 获取用户cookie
59 | export function getCookie(uid) {
60 | return axios.get(`//api.clicli.cc/cookie/${uid}`)
61 | }
62 |
63 | export function getUser(uname, uid, uqq) {
64 | return axios.get('//api.clicli.cc/user', {
65 | params: {
66 | uname,
67 | uid,
68 | uqq
69 | }
70 | })
71 | }
72 |
73 | // 替换用户cookie
74 | export function replaceCookie(data) {
75 | return axios.post('//api.clicli.cc/cookie/replace', {
76 | uid: parseInt(data.uid),
77 | hcy: data.hcy,
78 | quqi: data.quqi
79 | })
80 |
81 | }
82 |
83 | export function auth() {
84 | return axios.get('//api.clicli.cc/auth')
85 | }
--------------------------------------------------------------------------------
/packages/react/src/api/video.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios'
2 | import {replaceContent, isDev, API_LINK} from 'common/js/util'
3 | import Cookies from "js-cookie"
4 |
5 | const request = axios.create({
6 | baseURL: API_LINK
7 | })
8 |
9 | // 根据pid查找视频
10 | export function getVideos(pid, page, pageSize) {
11 | return request.get('/videos', {
12 | params: {
13 | pid: pid,
14 | page,
15 | pageSize
16 | }
17 | })
18 | }
19 |
20 | // 根据vid查找单一视频
21 |
22 | export function getVideo(vid) {
23 | return request.get(`/video/${vid}`)
24 |
25 | }
26 |
27 | // 添加视频
28 | export function addVideo({oid, title, content, pid, uid}) {
29 | content = replaceContent(content)
30 | return axios.post('/video/add', {
31 | oid: parseInt(oid),
32 | title,
33 | content,
34 | pid: parseInt(pid),
35 | uid
36 | }, {
37 | headers: {
38 | 'token': Cookies.get('token')
39 | }
40 | })
41 | }
42 |
43 | // 修改视频
44 | export function updateVideo({id, oid, title, content, pid, uid}) {
45 | content = replaceContent(content)
46 | return axios.post(`/video/update/${id}`, {
47 | oid: parseInt(oid),
48 | title,
49 | content,
50 | pid: parseInt(pid),
51 | uid
52 | }, {
53 | headers: {
54 | 'token': Cookies.get('token')
55 | }
56 | })
57 | }
58 |
59 | // 根据id删除视频
60 | export function deleteVideoById(id) {
61 | return axios.post(`/video/delete?id=${id}`, {}, {
62 | headers: {
63 | 'token': Cookies.get('token')
64 | }
65 | })
66 | }
67 |
68 | // 根据pid删除视频
69 | export function deleteVideoByPid(pid) {
70 | return axios.post(`/video/delete?pid=${pid}`, {}, {
71 | headers: {
72 | 'token': Cookies.get('token')
73 | }
74 | })
75 | }
76 |
77 |
78 | //上传
79 |
80 | export function getUploadToken(fname, rname) {
81 | return axios.get('https://jx.clicli.us/upload/auth', {
82 | params: {
83 | fname,
84 | rname
85 | }
86 | })
87 | }
--------------------------------------------------------------------------------
/packages/react/src/app.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | import Header from 'component/header/header'
4 | import EditorUser from 'component/editor-user/editor-user'
5 | import WriteArticle from 'component/write-article/wirte-article'
6 | import EditorVideo from 'component/editor-video/editor-video'
7 | import Login from 'component/login/login'
8 | import UserList from 'component/user-list/user-list'
9 | import ArticleList from 'component/post-list/post-list'
10 | import Register from 'component/register/register'
11 | import UserInfo from 'component/user-info/user-info'
12 |
13 | import {Route, Switch} from 'react-router-dom'
14 |
15 | class App extends React.Component {
16 | render() {
17 | return (
18 |
19 |
20 |
21 | (
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 | )}/>
37 |
38 | )
39 | }
40 | }
41 |
42 | export default App
--------------------------------------------------------------------------------
/packages/react/src/base/confirm/confirm.css:
--------------------------------------------------------------------------------
1 | .confirm {
2 | width: 280px;
3 | position: absolute;
4 | top: 50%;
5 | left: 50%;
6 | transform: translate(-50%, -50%);
7 | background: #fff;
8 | box-shadow: -1px 0px 1px rgba(70,123,150, 0.2)
9 |
10 | }
11 |
12 | .confirm .text {
13 | text-align: center;
14 | padding: 30px 0;
15 | }
16 |
17 | .confirm .option {
18 | display: flex;
19 | }
20 |
21 | .confirm .option li {
22 | display: block;
23 | flex: 1;
24 | text-align: center;
25 | cursor: pointer;
26 | }
27 |
28 | .confirm .option li:last-child {
29 | background: #7e5fd9;
30 | color: #fff;
31 | }
32 |
--------------------------------------------------------------------------------
/packages/react/src/base/confirm/confirm.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import './confirm.css'
3 |
4 | class Confirm extends React.Component {
5 | // constructor(props) {
6 | // super(props)
7 | // this.state = {
8 | // isShow: true
9 | // }
10 | // }
11 |
12 | closeShow() {
13 | this.props.closeShow()
14 | }
15 |
16 | confirm() {
17 | this.props.confirm(this.props.id)
18 | }
19 |
20 | render() {
21 | return (
22 |
23 |
24 | 确认删除吗?
25 |
26 |
30 |
31 | )
32 | }
33 | }
34 |
35 | export default Confirm
--------------------------------------------------------------------------------
/packages/react/src/base/list-view/list-view.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import './listview.css'
3 | import {Link} from 'react-router-dom'
4 | import Confirm from '../confirm/confirm'
5 | import {withRouter} from 'react-router-dom'
6 | import {deletePost} from 'api/post'
7 | import {deleteCommentByPid} from "api/comment"
8 | import {deleteVideoByPid} from "api/video"
9 |
10 | @withRouter
11 |
12 | class ListView extends React.Component {
13 | constructor(props) {
14 | super(props)
15 | this.state = {
16 | isShow: false,
17 | id: ''
18 | }
19 | }
20 |
21 | handleDelete(id) {
22 | Promise.all([deletePost(id), deleteCommentByPid(id), deleteVideoByPid(id)]).then(() => {
23 | this.props.refresh()
24 | })
25 |
26 | this.setState({
27 | isShow: false,
28 | id: '',
29 | })
30 | }
31 |
32 | handleShow(id) {
33 | this.setState({
34 | isShow: true,
35 | id: id
36 | })
37 | }
38 |
39 | closeShow() {
40 | this.setState({
41 | isShow: false
42 | })
43 | }
44 |
45 | render() {
46 | return (
47 |
48 |
49 | {this.state.isShow === true ?
: null}
51 |
52 |
53 | 标题
54 | 分类
55 | 状态
56 | 操作
57 |
58 |
73 |
74 | )
75 | }
76 | }
77 |
78 | export default ListView
--------------------------------------------------------------------------------
/packages/react/src/base/list-view/listview.css:
--------------------------------------------------------------------------------
1 | .article-list {
2 | width: 900px;
3 | margin: 50px auto;
4 | }
5 |
6 | .article-list h1 {
7 | color: #7e5fd9;
8 | font-size: 24px;
9 | padding: 10px;
10 | }
11 |
12 | .listview {
13 | box-shadow: 0px 1px 0px rgba(70, 75, 150, 0.2)
14 | }
15 |
16 | .listview li {
17 | display: flex;
18 | padding: 10px;
19 | border-bottom: 1px #ddd dashed;
20 | }
21 |
22 | .listview ul li:last-child {
23 | border: 0
24 | }
25 |
26 | .listview li .title {
27 | flex: 3;
28 | color: #7e5fd9;
29 | }
30 |
31 | .listview li .sort, .listview li .status, .listview li .action {
32 | flex: 1;
33 | }
34 |
35 | .listview li .action i {
36 | color: #7e5fd9;
37 | cursor: pointer;
38 | padding-right: 10px;
39 | }
40 |
41 | .reach-box input{
42 | background: #fff!important;
43 | margin: 20px 0;
44 | }
--------------------------------------------------------------------------------
/packages/react/src/base/loading/loading.css:
--------------------------------------------------------------------------------
1 | .loading{
2 | position: absolute;
3 | width: 100px;
4 | left: 50%;
5 | top: 50%;
6 | transform: translate(-50%,-50%);
7 | z-index: 1;
8 | }
9 |
10 | .loading .img{
11 | height: 18px;
12 | width: 18px;
13 | background: url(loading.gif);
14 | margin: 0 auto;
15 |
16 | }
17 |
18 | .loading .text{
19 | text-align: center;
20 | font-size: 12px;
21 | color: #7e5fd9;
22 | }
--------------------------------------------------------------------------------
/packages/react/src/base/loading/loading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cliclitv/fre-clicli/a60d1f6b647c5da69f29e046cee52d68adf1b072/packages/react/src/base/loading/loading.gif
--------------------------------------------------------------------------------
/packages/react/src/base/loading/loading.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import axios from 'axios'
3 | import './loading.css'
4 |
5 | class Loading extends React.Component {
6 | constructor(props) {
7 | super(props)
8 | this.state = {
9 | isShow: true
10 | }
11 | }
12 |
13 | componentWillMount() {
14 | this._isMounted = true
15 | }
16 |
17 | componentWillUnmount() {
18 | this._isMounted = false
19 | }
20 |
21 | render() {
22 | axios.interceptors.request.use((config) => {
23 | if (this._isMounted) {
24 | this.setState({
25 | isShow: true
26 | })
27 | }
28 |
29 | return config
30 | })
31 | axios.interceptors.response.use((config) => {
32 | if (this._isMounted) {
33 | this.setState({
34 | isShow: false
35 | })
36 | }
37 |
38 | return config
39 | })
40 | if (this.state.isShow === true) {
41 | return (
42 |
43 |
44 |
45 |
46 | 努力加载中……
47 |
48 |
49 | )
50 | } else {
51 | return null
52 | }
53 |
54 | }
55 |
56 | }
57 |
58 | export default Loading
--------------------------------------------------------------------------------
/packages/react/src/base/markdown/markdown.css:
--------------------------------------------------------------------------------
1 | /**
2 | * simplemde v1.11.2
3 | * Copyright Next Step Webs, Inc.
4 | * @link https://github.com/NextStepWebs/simplemde-markdown-editor
5 | * @license MIT
6 | */
7 |
8 | .CodeMirror {
9 | color: #000
10 | }
11 |
12 | .CodeMirror-lines {
13 | padding: 4px 0
14 | }
15 |
16 | .CodeMirror pre {
17 | padding: 0 4px
18 | }
19 |
20 | .CodeMirror-gutter-filler, .CodeMirror-scrollbar-filler {
21 | background-color: #fff
22 | }
23 |
24 | .CodeMirror-gutters {
25 | border-right: 1px solid #ddd;
26 | background-color: #f7f7f7;
27 | white-space: nowrap
28 | }
29 |
30 | .CodeMirror-linenumber {
31 | padding: 0 3px 0 5px;
32 | min-width: 20px;
33 | text-align: right;
34 | color: #999;
35 | white-space: nowrap
36 | }
37 |
38 | .CodeMirror-guttermarker {
39 | color: #000
40 | }
41 |
42 | .CodeMirror-guttermarker-subtle {
43 | color: #999
44 | }
45 |
46 | .CodeMirror-cursor {
47 | border-left: 1px solid #000;
48 | border-right: none;
49 | width: 0
50 | }
51 |
52 | .CodeMirror div.CodeMirror-secondarycursor {
53 | border-left: 1px solid silver
54 | }
55 |
56 | .cm-fat-cursor .CodeMirror-cursor {
57 | width: auto;
58 | border: 0 !important;
59 | background: #7e7
60 | }
61 |
62 | .cm-fat-cursor div.CodeMirror-cursors {
63 | z-index: 1
64 | }
65 |
66 | .cm-animate-fat-cursor {
67 | width: auto;
68 | border: 0;
69 | -webkit-animation: blink 1.06s steps(1) infinite;
70 | -moz-animation: blink 1.06s steps(1) infinite;
71 | animation: blink 1.06s steps(1) infinite;
72 | background-color: #7e7
73 | }
74 |
75 | @-moz-keyframes blink {
76 | 50% {
77 | background-color: transparent
78 | }
79 | }
80 |
81 | @-webkit-keyframes blink {
82 | 50% {
83 | background-color: transparent
84 | }
85 | }
86 |
87 | @keyframes blink {
88 | 50% {
89 | background-color: transparent
90 | }
91 | }
92 |
93 | .cm-tab {
94 | display: inline-block;
95 | text-decoration: inherit
96 | }
97 |
98 | .CodeMirror-ruler {
99 | border-left: 1px solid #ccc;
100 | position: absolute
101 | }
102 |
103 | .cm-s-default .cm-header {
104 | color: #00f
105 | }
106 |
107 | .cm-s-default .cm-quote {
108 | color: #090
109 | }
110 |
111 | .cm-negative {
112 | color: #d44
113 | }
114 |
115 | .cm-positive {
116 | color: #292
117 | }
118 |
119 | .cm-header, .cm-strong {
120 | font-weight: 700
121 | }
122 |
123 | .cm-em {
124 | font-style: italic
125 | }
126 |
127 | .cm-link {
128 | text-decoration: underline
129 | }
130 |
131 | .cm-strikethrough {
132 | text-decoration: line-through
133 | }
134 |
135 | .cm-s-default .cm-keyword {
136 | color: #708
137 | }
138 |
139 | .cm-s-default .cm-atom {
140 | color: #219
141 | }
142 |
143 | .cm-s-default .cm-number {
144 | color: #164
145 | }
146 |
147 | .cm-s-default .cm-def {
148 | color: #00f
149 | }
150 |
151 | .cm-s-default .cm-variable-2 {
152 | color: #05a
153 | }
154 |
155 | .cm-s-default .cm-variable-3 {
156 | color: #085
157 | }
158 |
159 | .cm-s-default .cm-comment {
160 | color: #a50
161 | }
162 |
163 | .cm-s-default .cm-string {
164 | color: #a11
165 | }
166 |
167 | .cm-s-default .cm-string-2 {
168 | color: #f50
169 | }
170 |
171 | .cm-s-default .cm-meta, .cm-s-default .cm-qualifier {
172 | color: #555
173 | }
174 |
175 | .cm-s-default .cm-builtin {
176 | color: #30a
177 | }
178 |
179 | .cm-s-default .cm-bracket {
180 | color: #997
181 | }
182 |
183 | .cm-s-default .cm-tag {
184 | color: #170
185 | }
186 |
187 | .cm-s-default .cm-attribute {
188 | color: #00c
189 | }
190 |
191 | .cm-s-default .cm-hr {
192 | color: #999
193 | }
194 |
195 | .cm-s-default .cm-link {
196 | color: #00c
197 | }
198 |
199 | .cm-invalidchar, .cm-s-default .cm-error {
200 | color: red
201 | }
202 |
203 | .CodeMirror-composing {
204 | border-bottom: 2px solid
205 | }
206 |
207 | div.CodeMirror span.CodeMirror-matchingbracket {
208 | color: #0f0
209 | }
210 |
211 | div.CodeMirror span.CodeMirror-nonmatchingbracket {
212 | color: #f22
213 | }
214 |
215 | .CodeMirror-matchingtag {
216 | background: rgba(255, 150, 0, .3)
217 | }
218 |
219 | .CodeMirror-activeline-background {
220 | background: #e8f2ff
221 | }
222 |
223 | .CodeMirror {
224 | position: relative;
225 | overflow: hidden;
226 | background: #fff
227 | }
228 |
229 | .CodeMirror-scroll {
230 | overflow: scroll !important;
231 | margin-bottom: -30px;
232 | margin-right: -30px;
233 | padding-bottom: 30px;
234 | height: 100%;
235 | outline: 0;
236 | position: relative
237 | }
238 |
239 | .CodeMirror-sizer {
240 | position: relative;
241 | border-right: 30px solid transparent
242 | }
243 |
244 | .CodeMirror-gutter-filler, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-vscrollbar {
245 | position: absolute;
246 | z-index: 6;
247 | display: none
248 | }
249 |
250 | .CodeMirror-vscrollbar {
251 | right: 0;
252 | top: 0;
253 | overflow-x: hidden;
254 | overflow-y: scroll
255 | }
256 |
257 | .CodeMirror-hscrollbar {
258 | bottom: 0;
259 | left: 0;
260 | overflow-y: hidden;
261 | overflow-x: scroll
262 | }
263 |
264 | .CodeMirror-scrollbar-filler {
265 | right: 0;
266 | bottom: 0
267 | }
268 |
269 | .CodeMirror-gutter-filler {
270 | left: 0;
271 | bottom: 0
272 | }
273 |
274 | .CodeMirror-gutters {
275 | position: absolute;
276 | left: 0;
277 | top: 0;
278 | min-height: 100%;
279 | z-index: 3
280 | }
281 |
282 | .CodeMirror-gutter {
283 | white-space: normal;
284 | height: 100%;
285 | display: inline-block;
286 | vertical-align: top;
287 | margin-bottom: -30px
288 | }
289 |
290 | .CodeMirror-gutter-wrapper {
291 | position: absolute;
292 | z-index: 4;
293 | background: 0 0 !important;
294 | border: none !important;
295 | -webkit-user-select: none;
296 | -moz-user-select: none;
297 | user-select: none
298 | }
299 |
300 | .CodeMirror-gutter-background {
301 | position: absolute;
302 | top: 0;
303 | bottom: 0;
304 | z-index: 4
305 | }
306 |
307 | .CodeMirror-gutter-elt {
308 | position: absolute;
309 | cursor: default;
310 | z-index: 4
311 | }
312 |
313 | .CodeMirror-lines {
314 | cursor: text;
315 | min-height: 1px
316 | }
317 |
318 | .CodeMirror pre {
319 | -moz-border-radius: 0;
320 | -webkit-border-radius: 0;
321 | border-radius: 0;
322 | border-width: 0;
323 | background: 0 0;
324 | font-family: inherit;
325 | font-size: inherit;
326 | margin: 0;
327 | white-space: pre;
328 | word-wrap: normal;
329 | line-height: inherit;
330 | color: inherit;
331 | z-index: 2;
332 | position: relative;
333 | overflow: visible;
334 | -webkit-tap-highlight-color: transparent;
335 | -webkit-font-variant-ligatures: none;
336 | font-variant-ligatures: none
337 | }
338 |
339 | .CodeMirror-wrap pre {
340 | word-wrap: break-word;
341 | white-space: pre-wrap;
342 | word-break: normal
343 | }
344 |
345 | .CodeMirror-linebackground {
346 | position: absolute;
347 | left: 0;
348 | right: 0;
349 | top: 0;
350 | bottom: 0;
351 | z-index: 0
352 | }
353 |
354 | .CodeMirror-linewidget {
355 | position: relative;
356 | z-index: 2;
357 | overflow: auto
358 | }
359 |
360 | .CodeMirror-code {
361 | outline: 0
362 | }
363 |
364 | .CodeMirror-gutter, .CodeMirror-gutters, .CodeMirror-linenumber, .CodeMirror-scroll, .CodeMirror-sizer {
365 | -moz-box-sizing: content-box;
366 | box-sizing: content-box
367 | }
368 |
369 | .CodeMirror-measure {
370 | position: absolute;
371 | width: 100%;
372 | height: 0;
373 | overflow: hidden;
374 | visibility: hidden
375 | }
376 |
377 | .CodeMirror-cursor {
378 | position: absolute
379 | }
380 |
381 | .CodeMirror-measure pre {
382 | position: static
383 | }
384 |
385 | div.CodeMirror-cursors {
386 | visibility: hidden;
387 | position: relative;
388 | z-index: 3
389 | }
390 |
391 | .CodeMirror-focused div.CodeMirror-cursors, div.CodeMirror-dragcursors {
392 | visibility: visible
393 | }
394 |
395 | .CodeMirror-selected {
396 | background: #d9d9d9
397 | }
398 |
399 | .CodeMirror-focused .CodeMirror-selected, .CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection {
400 | background: #d7d4f0
401 | }
402 |
403 | .CodeMirror-crosshair {
404 | cursor: crosshair
405 | }
406 |
407 | .CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection {
408 | background: #d7d4f0
409 | }
410 |
411 | .cm-searching {
412 | background: #ffa;
413 | background: rgba(255, 255, 0, .4)
414 | }
415 |
416 | .cm-force-border {
417 | padding-right: .1px
418 | }
419 |
420 | @media print {
421 | .CodeMirror div.CodeMirror-cursors {
422 | visibility: hidden
423 | }
424 | }
425 |
426 | .cm-tab-wrap-hack:after {
427 | content: ''
428 | }
429 |
430 | span.CodeMirror-selectedtext {
431 | background: 0 0
432 | }
433 |
434 | .CodeMirror {
435 | height: auto;
436 | min-height: 300px;
437 | box-shadow: 1px 1px 1px rgba(70, 75, 150, 0.2);
438 | padding: 10px;
439 | font: inherit;
440 | z-index: 1
441 | }
442 |
443 | .CodeMirror-scroll {
444 | min-height: 300px
445 | }
446 |
447 | .CodeMirror-fullscreen {
448 | background: #fff;
449 | position: fixed !important;
450 | top: 50px;
451 | left: 0;
452 | right: 0;
453 | bottom: 0;
454 | height: auto;
455 | z-index: 9
456 | }
457 |
458 | .CodeMirror-sided {
459 | width: 50% !important
460 | }
461 |
462 | .editor-toolbar {
463 | position: relative;
464 | opacity: .6;
465 | -webkit-user-select: none;
466 | -moz-user-select: none;
467 | -ms-user-select: none;
468 | -o-user-select: none;
469 | user-select: none;
470 | }
471 |
472 | .editor-toolbar:after, .editor-toolbar:before {
473 | display: block;
474 | content: ' ';
475 | height: 1px
476 | }
477 |
478 | .editor-toolbar:before {
479 | margin-bottom: 5px
480 | }
481 |
482 | .editor-toolbar:after {
483 | margin-top: 5px
484 | }
485 |
486 | .editor-toolbar:hover, .editor-wrapper input.title:focus, .editor-wrapper input.title:hover {
487 | opacity: .8
488 | }
489 |
490 | .editor-toolbar.fullscreen {
491 | width: 100%;
492 | height: 50px;
493 | overflow-x: auto;
494 | overflow-y: hidden;
495 | white-space: nowrap;
496 | padding-top: 10px;
497 | padding-bottom: 10px;
498 | box-sizing: border-box;
499 | background: #fff;
500 | border: 0;
501 | position: fixed;
502 | top: 0;
503 | left: 0;
504 | opacity: 1;
505 | z-index: 9
506 | }
507 |
508 | .editor-toolbar.fullscreen::before {
509 | width: 20px;
510 | height: 50px;
511 | background: -moz-linear-gradient(left, rgba(255, 255, 255, 1) 0, rgba(255, 255, 255, 0) 100%);
512 | background: -webkit-gradient(linear, left top, right top, color-stop(0, rgba(255, 255, 255, 1)), color-stop(100%, rgba(255, 255, 255, 0)));
513 | background: -webkit-linear-gradient(left, rgba(255, 255, 255, 1) 0, rgba(255, 255, 255, 0) 100%);
514 | background: -o-linear-gradient(left, rgba(255, 255, 255, 1) 0, rgba(255, 255, 255, 0) 100%);
515 | background: -ms-linear-gradient(left, rgba(255, 255, 255, 1) 0, rgba(255, 255, 255, 0) 100%);
516 | background: linear-gradient(to right, rgba(255, 255, 255, 1) 0, rgba(255, 255, 255, 0) 100%);
517 | position: fixed;
518 | top: 0;
519 | left: 0;
520 | margin: 0;
521 | padding: 0
522 | }
523 |
524 | .editor-toolbar.fullscreen::after {
525 | width: 20px;
526 | height: 50px;
527 | background: -moz-linear-gradient(left, rgba(255, 255, 255, 0) 0, rgba(255, 255, 255, 1) 100%);
528 | background: -webkit-gradient(linear, left top, right top, color-stop(0, rgba(255, 255, 255, 0)), color-stop(100%, rgba(255, 255, 255, 1)));
529 | background: -webkit-linear-gradient(left, rgba(255, 255, 255, 0) 0, rgba(255, 255, 255, 1) 100%);
530 | background: -o-linear-gradient(left, rgba(255, 255, 255, 0) 0, rgba(255, 255, 255, 1) 100%);
531 | background: -ms-linear-gradient(left, rgba(255, 255, 255, 0) 0, rgba(255, 255, 255, 1) 100%);
532 | background: linear-gradient(to right, rgba(255, 255, 255, 0) 0, rgba(255, 255, 255, 1) 100%);
533 | position: fixed;
534 | top: 0;
535 | right: 0;
536 | margin: 0;
537 | padding: 0
538 | }
539 |
540 | .editor-toolbar a {
541 | display: inline-block;
542 | text-align: center;
543 | text-decoration: none !important;
544 | color: #2c3e50 !important;
545 | width: 25px;
546 | height: 25px;
547 | margin: 0;
548 | cursor: pointer;
549 | }
550 |
551 | .editor-toolbar a.active, .editor-toolbar a:hover {
552 | background: #E9E9E6;
553 | }
554 |
555 | .editor-toolbar a:before {
556 | line-height: 25px
557 | }
558 |
559 | .editor-toolbar i.separator {
560 | display: inline-block;
561 | width: 0;
562 | border-left: 1px solid #d9d9d9;
563 | border-right: 1px solid #fff;
564 | color: transparent;
565 | text-indent: -10px;
566 | margin: 0 6px
567 | }
568 |
569 | .editor-toolbar a.fa-header-x:after {
570 | font-family: Arial, "Helvetica Neue", Helvetica, sans-serif;
571 | font-size: 65%;
572 | vertical-align: text-bottom;
573 | position: relative;
574 | top: 2px
575 | }
576 |
577 | .editor-toolbar a.fa-header-1:after {
578 | content: "1"
579 | }
580 |
581 | .editor-toolbar a.fa-header-2:after {
582 | content: "2"
583 | }
584 |
585 | .editor-toolbar a.fa-header-3:after {
586 | content: "3"
587 | }
588 |
589 | .editor-toolbar a.fa-header-bigger:after {
590 | content: "▲"
591 | }
592 |
593 | .editor-toolbar a.fa-header-smaller:after {
594 | content: "▼"
595 | }
596 |
597 | .editor-toolbar.disabled-for-preview a:not(.no-disable) {
598 | pointer-events: none;
599 | background: #fff;
600 | border-color: transparent;
601 | text-shadow: inherit
602 | }
603 |
604 | @media only screen and (max-width: 700px) {
605 | .editor-toolbar a.no-mobile {
606 | display: none
607 | }
608 | }
609 |
610 | .editor-statusbar {
611 | padding: 8px 10px;
612 | font-size: 12px;
613 | color: #959694;
614 | text-align: right
615 | }
616 |
617 | .editor-statusbar span {
618 | display: inline-block;
619 | min-width: 4em;
620 | margin-left: 1em
621 | }
622 |
623 | .editor-preview, .editor-preview-side {
624 | padding: 10px;
625 | background: #fafafa;
626 | overflow: auto;
627 | display: none;
628 | box-sizing: border-box
629 | }
630 |
631 | .editor-statusbar .lines:before {
632 | content: 'lines: '
633 | }
634 |
635 | .editor-statusbar .words:before {
636 | content: 'words: '
637 | }
638 |
639 | .editor-statusbar .characters:before {
640 | content: 'characters: '
641 | }
642 |
643 | .editor-preview {
644 | position: absolute;
645 | width: 100%;
646 | height: 100%;
647 | top: 0;
648 | left: 0;
649 | z-index: 7
650 | }
651 |
652 | .editor-preview-side {
653 | position: fixed;
654 | bottom: 0;
655 | width: 50%;
656 | top: 50px;
657 | right: 0;
658 | z-index: 9;
659 | border: 1px solid #ddd
660 | }
661 |
662 | .editor-preview-active, .editor-preview-active-side {
663 | display: block
664 | }
665 |
666 | .editor-preview-side > p, .editor-preview > p {
667 | margin-top: 0
668 | }
669 |
670 | .editor-preview pre, .editor-preview-side pre {
671 | background: #eee;
672 | margin-bottom: 10px
673 | }
674 |
675 | .editor-preview table td, .editor-preview table th, .editor-preview-side table td, .editor-preview-side table th {
676 | border: 1px solid #ddd;
677 | padding: 5px
678 | }
679 |
680 | .CodeMirror .CodeMirror-code .cm-tag {
681 | color: #63a35c
682 | }
683 |
684 | .CodeMirror .CodeMirror-code .cm-attribute {
685 | color: #795da3
686 | }
687 |
688 | .CodeMirror .CodeMirror-code .cm-string {
689 | color: #183691
690 | }
691 |
692 | .CodeMirror .CodeMirror-selected {
693 | background: #d9d9d9
694 | }
695 |
696 | .CodeMirror .CodeMirror-code .cm-header-1 {
697 | font-size: 200%;
698 | line-height: 200%
699 | }
700 |
701 | .CodeMirror .CodeMirror-code .cm-header-2 {
702 | font-size: 160%;
703 | line-height: 160%
704 | }
705 |
706 | .CodeMirror .CodeMirror-code .cm-header-3 {
707 | font-size: 125%;
708 | line-height: 125%
709 | }
710 |
711 | .CodeMirror .CodeMirror-code .cm-header-4 {
712 | font-size: 110%;
713 | line-height: 110%
714 | }
715 |
716 | .CodeMirror .CodeMirror-code .cm-comment {
717 | background: rgba(0, 0, 0, .05);
718 | border-radius: 2px
719 | }
720 |
721 | .CodeMirror .CodeMirror-code .cm-link {
722 | color: #7f8c8d
723 | }
724 |
725 | .CodeMirror .CodeMirror-code .cm-url {
726 | color: #aab2b3
727 | }
728 |
729 | .CodeMirror .CodeMirror-code .cm-strikethrough {
730 | text-decoration: line-through
731 | }
732 |
733 | .CodeMirror .CodeMirror-placeholder {
734 | opacity: .5
735 | }
736 |
737 | .CodeMirror .cm-spell-error:not(.cm-url):not(.cm-comment):not(.cm-tag):not(.cm-word) {
738 | background: rgba(255, 0, 0, .15)
739 | }
--------------------------------------------------------------------------------
/packages/react/src/base/markdown/markdown.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import Mde from 'simplemde'
3 | import './markdown.css'
4 |
5 | class Markdown extends React.Component {
6 |
7 | componentDidMount() {
8 | this.loadEditor()
9 | }
10 |
11 | componentWillReceiveProps(nextProps) {
12 | if (this.props.defaultValue !== nextProps.defaultValue) {
13 | this.mde.value(nextProps.defaultValue)
14 | }
15 | }
16 |
17 | loadEditor() {
18 | this.mde = new Mde({
19 | element:this.marked,
20 | autoDownloadFontAwesome: true,
21 | status: false,
22 | spellChecker: false,
23 | forceSync: true
24 | })
25 |
26 | this.bindMde()
27 | }
28 |
29 | bindMde() {
30 | this.mde.codemirror.on('change', () => {
31 | this.props.handleMde(this.mde.value())
32 | })
33 | }
34 |
35 | render() {
36 | return (
37 |
38 |
39 |
40 | )
41 | }
42 | }
43 |
44 | export default Markdown
--------------------------------------------------------------------------------
/packages/react/src/base/reach-box/reach-box.css:
--------------------------------------------------------------------------------
1 | .reach-box input {
2 | padding: 10px;
3 | box-shadow: 1px 1px 1px rgba(70, 75, 150, 0.2);
4 | border: 0;
5 | width: 300px;
6 | margin-right: 20px;
7 | box-sizing: border-box;
8 | background: #F6F6F3;
9 | }
10 |
11 | .reach-box button {
12 | background: #7e5fd9;
13 | padding: 8px 30px;
14 | color: #fff;
15 | margin: 0 auto;
16 | border: 0;
17 | box-shadow: 1px 1px 1px rgba(70, 75, 150, 0.6);
18 | cursor: pointer;
19 | }
--------------------------------------------------------------------------------
/packages/react/src/base/reach-box/reach-box.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import './reach-box.css'
3 | import {withRouter} from "react-router-dom"
4 |
5 | @withRouter
6 |
7 | class ReachBox extends React.Component {
8 | constructor(props) {
9 | super(props)
10 | this.state = {
11 | v: ''
12 | }
13 | }
14 |
15 | selectInput() {
16 | this.props.history.push(`${this.props.prefix}${this.state.v}`)
17 | }
18 |
19 | handleChange(v) {
20 | this.setState({
21 | v
22 | })
23 | }
24 |
25 | render() {
26 | return (
27 |
28 | this.handleChange(e.target.value)}/>
29 |
30 |
31 | )
32 | }
33 |
34 | }
35 |
36 | export default ReachBox
--------------------------------------------------------------------------------
/packages/react/src/base/top-tip/top-tip.css:
--------------------------------------------------------------------------------
1 | .toptip {
2 | position: fixed;
3 | width: 100%;
4 | padding: 10px;
5 | color: #fff;
6 | top: -40px;
7 | text-align: center;
8 | z-index: 999;
9 | animation: moveup 5s ease-in-out infinite;
10 | }
11 |
12 | @keyframes moveup {
13 | 0% {
14 | top: -40px;
15 | opacity: 1;
16 | }
17 | 25%{
18 | top: 0;
19 | opacity: 1;
20 | }
21 | 50%{
22 | opacity: 1;
23 | }
24 | 100% {
25 | top: 0;
26 | opacity: 0;
27 | }
28 | }
--------------------------------------------------------------------------------
/packages/react/src/base/top-tip/top-tip.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import './top-tip.css'
3 |
4 |
5 | class TopTip extends React.Component {
6 |
7 | render() {
8 | let text = this.props.text
9 | return (
10 |
11 | {text}
12 |
13 | )
14 | }
15 | }
16 |
17 | export default TopTip
--------------------------------------------------------------------------------
/packages/react/src/common/js/axios.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cliclitv/fre-clicli/a60d1f6b647c5da69f29e046cee52d68adf1b072/packages/react/src/common/js/axios.js
--------------------------------------------------------------------------------
/packages/react/src/common/js/util.js:
--------------------------------------------------------------------------------
1 | import md5 from 'blueimp-md5'
2 | import Cookies from 'js-cookie'
3 |
4 | export function getAvatar(avatar) {
5 | if (!avatar) return ''
6 | if (/^[0-9]+$/.test(avatar)) {
7 | return `http://q1.qlogo.cn/g?b=qq&nk=${avatar}&s=5`
8 | } else {
9 | let hash = md5(avatar)
10 | return `https://sdn.geekzu.org/avatar/${hash}`
11 | }
12 | }
13 |
14 | export function replaceContent(content) {
15 | content = content.replace('piaoquantv', 'yishihui')
16 | return content
17 | }
18 |
19 | export let isDev = process.env.NODE_ENV === 'development'
20 | export const HOME_LINK = '//www.clicli.cc'
21 | export const API_LINK = '//api.clicli.cc'
22 |
--------------------------------------------------------------------------------
/packages/react/src/common/style/iconfont.css:
--------------------------------------------------------------------------------
1 |
2 | @font-face {font-family: "icon-font";
3 | src: url('//at.alicdn.com/t/font_474499_sbdek9r9luucjtt9.eot?t=1519207777376'); /* IE9*/
4 | src: url('//at.alicdn.com/t/font_474499_sbdek9r9luucjtt9.eot?t=1519207777376#iefix') format('embedded-opentype'), /* IE6-IE8 */
5 | url('data:application/x-font-woff;charset=utf-8;base64,d09GRgABAAAAAAZAAAsAAAAACSwAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABHU1VCAAABCAAAADMAAABCsP6z7U9TLzIAAAE8AAAARAAAAFZW7kiWY21hcAAAAYAAAABxAAABsgKC1C5nbHlmAAAB9AAAAkEAAALEomRh/mhlYWQAAAQ4AAAALwAAADYQhhCnaGhlYQAABGgAAAAcAAAAJAfeA4ZobXR4AAAEhAAAABMAAAAUE+kAAGxvY2EAAASYAAAADAAAAAwBcgISbWF4cAAABKQAAAAeAAAAIAEUAF1uYW1lAAAExAAAAUoAAAJ5PNf/ynBvc3QAAAYQAAAAMAAAAEGh1WBeeJxjYGRgYOBikGPQYWB0cfMJYeBgYGGAAJAMY05meiJQDMoDyrGAaQ4gZoOIAgCKIwNPAHicY2Bk/s04gYGVgYOpk+kMAwNDP4RmfM1gxMjBwMDEwMrMgBUEpLmmMDgwVDxbydzwv4EhhrmBoQEozAiSAwAw4A0YeJzFkcENgDAIRR+2GmMcxSGcwxk8eXIAl3Ex1tDf4kEn8JPXwA+hDQVaIIlJZLANo2iVa9VPDNXPzKoHehrF7osffl6XvHceMvVFlDypv8zu+E3239VfjfWcn0pbYX/QE30Jyo/4EWh3+BmQb4zoGXgAAAB4nH2RS2sTURTHz7k3M5PUTJK580qmmSSTycwkNMZmJo/S0lTBRVOkCCLq0sdWNwoFUYhgpQsf0aWCoAh+BqWLuNZPIG6kbnTVL5DRO1TEhXg5XP7n3AP/c34XBICfX+k+LYIKTejCaTgLgOIS1nPERifodcgS6o6gm1qOBm7gSG69Q9fRrIuaEQ56vilKYh5zWMHICQdBhwTY743IGoaGjVhatM4xr8zoFBeKQWU33iKvUa+65fzoeDxub2hhTU3vZBkrMfYwLQpCmpBUPofXTSMjZBbE+I2Qt/T9aotUMVsKrDOX5Noiu7zXu2F7ZgZxMkF1sZZ7u6FYCo87lqGyklSQ00VLdhsa7nw7VlSztn8A/CS7fqDP6AZkQIYClMHmuwbDQVhFQ5MwQBOHphAamig5HewNIoeuPB2zrrrKWKxPcW86v3XxMb4qaFphfjuv63nygJyfbjK2qi6rScfuNBZ+PHmkVzVEraoDpLjnjN6jp7inDT6c4I4dlFxflDhVRTMSan0lIek6CVOvN4xMRawHlAs9EWQm9Z2PzrKEk1j2mvip6TU9rzl/zm98gSNMraRmuEb7KQpeGbHsnfwS+w3fb+Dn1laLR5FDja9UKvjytzia6z49pNeAQQMGsMnn4v76n4n4x7vU6db9dQ5i6ISGqefQ7f+r0sF+N4F1VJHozXkpGm9G5CDaVp22dTcuyIzJeJhliIr8v4xe3Y7mdjgeR+R7qV1X5xcUGfkT75CV93/pd7xZZkoi8RcLBXkRAAAAeJxjYGRgYADil7NO9Mbz23xl4GZhAIFrm9MSEfT/FhYG5hQgl4OBCSQKAFITCyEAeJxjYGRgYG7438AQw8IAAkCSkQEVsAIARwsCbnicY2FgYGB+ycDAwoDAAA6bAP0AAAAAAAB2ALAA/AFieJxjYGRgYGBlCARiEGACYi4gZGD4D+YzAAARLQFyAAB4nG2RvU4CQRSFz/JnWKIFRkudRgsNy09jQikJFHYU9LDMLpD9y+xAwiP4PD6DT2Bv5zPYelguFMhu5ua7554zuckAaOIbDvbfDc+eHdTZ7bmEC9wJl6k/CFfInnAVDbwI16i/Crt4xptwA9fY8AanUmf3hHdhhzt8CJdwhU/hMvUv4Qr5R7iKW/wK19B0LoVdTJx74QYenbU7MHpq9VzNtmrpp0mQJtbdQWtHYx2uo6k59keYaJMv00R1vc5RG+lEm8Nd+SbsWRuowKSxGnKqoyhVmUlX2rfewtqs324Hont+GnO1AQw0prCscyjMsGVdwkeKBEFRLX0HpXXUxkyEWCNi2pyZ/1cmTBjknOx6hS6fqXPGN6IvKbyne+V8qBA9qpZuxWOYiUlDyWruE5EVsmK2ouJT97AoUhn6aPMPTvxesUX8Bx1ocJYAAHicY2BigAAuBuyAlZGJkZmRhZGVkY2BsYItNSWzJL+IOSU1h6UktaKEgQEARuIGMg==') format('woff'),
6 | url('//at.alicdn.com/t/font_474499_sbdek9r9luucjtt9.ttf?t=1519207777376') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
7 | url('//at.alicdn.com/t/font_474499_sbdek9r9luucjtt9.svg?t=1519207777376#icon-font') format('svg'); /* iOS 4.1- */
8 | }
9 |
10 | .icon-font {
11 | font-family:"icon-font" !important;
12 | font-size:16px;
13 | font-style:normal;
14 | -webkit-font-smoothing: antialiased;
15 | -moz-osx-font-smoothing: grayscale;
16 | }
17 |
18 | .icon-editor:before { content: "\e684"; }
19 |
20 | .icon-del:before { content: "\e65a"; }
21 |
22 | .icon-text:before { content: "\e6a9"; }
23 |
24 |
--------------------------------------------------------------------------------
/packages/react/src/common/style/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | font: 14px 微软雅黑;
3 | color: #444;
4 | background: #f4f6fa;
5 | }
6 |
7 | a {
8 | color: #7e5fd9;
9 | }
10 |
11 | .center {
12 | text-align: center;
13 | }
14 |
15 | li {
16 | list-style: none;
17 | }
18 |
--------------------------------------------------------------------------------
/packages/react/src/common/style/reset.css:
--------------------------------------------------------------------------------
1 | /* http://meyerweb.com/eric/tools/css/reset/
2 | v2.0 | 20110126
3 | License: none (public domain)
4 | */
5 |
6 | html, body, div, span, applet, object, iframe,
7 | h1, h2, h3, h4, h5, h6, p, blockquote, pre,
8 | a, abbr, acronym, address, big, cite, code,
9 | del, dfn, em, img, ins, kbd, q, s, samp,
10 | small, strike, strong, sub, sup, tt, var,
11 | b, u, i, center,
12 | dl, dt, dd, ol, ul, li,
13 | fieldset, form, label, legend,
14 | table, caption, tbody, tfoot, thead, tr, th, td,
15 | article, aside, canvas, details, embed,
16 | figure, figcaption, footer, header, hgroup,
17 | menu, nav, output, ruby, section, summary,
18 | time, mark, audio, video {
19 | margin: 0;
20 | padding: 0;
21 | border: 0;
22 | font-size: 100%;
23 | font: inherit;
24 | vertical-align: baseline;
25 | }
26 |
27 | /* HTML5 display-role reset for older browsers */
28 | article, aside, details, figcaption, figure,
29 | footer, header, hgroup, menu, nav, section {
30 | display: block;
31 | }
32 |
33 | body {
34 | line-height: 1;
35 | }
36 |
37 | ol, ul {
38 | list-style: none;
39 | }
40 |
41 | blockquote, q {
42 | quotes: none;
43 | }
44 |
45 | blockquote:before, blockquote:after,
46 | q:before, q:after {
47 | content: '';
48 | content: none;
49 | }
50 |
51 | table {
52 | border-collapse: collapse;
53 | border-spacing: 0;
54 | }
55 |
56 | a{
57 | text-decoration: none;
58 | }
--------------------------------------------------------------------------------
/packages/react/src/component/editor-user/editor-user.css:
--------------------------------------------------------------------------------
1 | .editor-user {
2 | width: 800px;
3 | margin: 50px auto;
4 | }
5 |
6 | .editor-user h1 {
7 | color: #7e5fd9;
8 | font-size: 24px;
9 | margin: 20px 0;
10 | }
11 |
12 | .editor-user li {
13 | padding: 10px;
14 | font-weight: bold;
15 | }
16 |
17 | .editor-user span {
18 | cursor: pointer;
19 | }
20 |
21 | .editor-user ul {
22 | width: 500px;
23 | margin: 50px auto;
24 | }
25 |
26 | .editor-user li input, textarea {
27 | padding: 10px;
28 | box-shadow: 1px 1px 1px rgba(70, 75, 150, 0.2);
29 | border: 0;
30 | width: 100%;
31 | margin: 10px 0;
32 | box-sizing: border-box;
33 | }
34 |
35 | .editor-user li textarea {
36 | height: 50px;
37 | }
38 |
39 | .editor-user button {
40 | background: #7e5fd9;
41 | padding: 8px 30px;
42 | color: #fff;
43 | margin: 20px;
44 | border: 0;
45 | box-shadow: 1px 1px 1px rgba(70, 75, 150, 0.6);
46 | cursor: pointer;
47 | }
48 |
49 | .editor-user select {
50 | padding: 5px 17px;
51 | box-shadow: 1px 1px 1px rgba(70, 75, 150, 0.2);
52 | border: 0;
53 | color: #666;
54 | margin: 10px 0;
55 | display: block;
56 | }
57 |
58 | .per {
59 | position: absolute;
60 | top: 50%;
61 | left: 50%;
62 | transform: translate(-50%, -50%);
63 | height: 60px;
64 | width: 60px;
65 | color: #fff;
66 | font-size: 20px;
67 | background: #608ea8;
68 | text-align: center;
69 | border-radius: 30px;
70 | line-height: 60px;
71 | }
72 |
73 | #uploader{
74 | position: relative;
75 | }
76 |
77 | #uploader input{
78 | opacity: 0;
79 | position: absolute;
80 | top: 0;
81 | left: 0;
82 | width: 100px;
83 | height: 35px;
84 | }
85 |
86 | #uploader span{
87 | position: absolute;
88 | top: 15px;
89 | left: 0;
90 | background: #6c43b6;
91 | color: #fff;
92 | width: 100px;
93 | text-align: center;
94 | line-height: 35px;
95 | box-shadow: 1px 1px 1px rgba(70, 75, 150, 0.6);
96 | cursor: pointer;
97 | height: 35px;
98 | }
--------------------------------------------------------------------------------
/packages/react/src/component/editor-user/editor-user.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | import TopTip from 'base/top-tip/top-tip'
4 |
5 | import {getUser, update} from 'api/user'
6 | import {adminAuth} from "hoc/auth/auth"
7 |
8 | import './editor-user.css'
9 |
10 | @adminAuth
11 | class EditorUser extends React.Component {
12 |
13 | constructor(props) {
14 | super(props)
15 | this.state = {
16 | qq: this.props.match.params.qq,
17 | msg: '',
18 | name: '',
19 | desc: '',
20 | level: ''
21 | }
22 | }
23 |
24 | componentDidMount() {
25 | this.loadUser()
26 | }
27 |
28 | loadUser() {
29 | getUser('', 0, this.state.qq).then(res => {
30 | if (res.data.code === 200) {
31 | this.setState(res.data.result)
32 | }
33 | })
34 | }
35 |
36 | handleChange(key, val) {
37 | this.setState({
38 | [key]: val
39 | })
40 | }
41 |
42 | handleClick() {
43 | update(this.state).then(res => {
44 | this.setState({
45 | msg: res.data.msg
46 | })
47 | setTimeout(() => {
48 | this.setState({
49 | msg: ''
50 | })
51 | }, 5000)
52 | })
53 | }
54 |
55 | render() {
56 | return (
57 |
58 | {this.state.msg ?
: null}
59 |
60 |
88 |
89 | )
90 | }
91 | }
92 |
93 | export default EditorUser
--------------------------------------------------------------------------------
/packages/react/src/component/editor-video/editor-video.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import TopTip from 'base/top-tip/top-tip'
3 | import {getVideo, updateVideo, deleteVideoById, addVideo, getUploadToken} from "api/video"
4 | import {adminAuth} from "hoc/auth/auth"
5 | import {withRouter} from 'react-router-dom'
6 |
7 | import '../editor-user/editor-user.css'
8 | import Cookies from "js-cookie"
9 |
10 | @adminAuth
11 | @withRouter
12 | class EditorVideo extends React.Component {
13 |
14 | constructor(props) {
15 | super(props)
16 | this.state = {
17 | id: this.props.match.params.id,
18 | oid: '',
19 | title: '',
20 | content: '',
21 | pid: this.props.match.params.pid,
22 | text: '修改',
23 | uid: parseInt(Cookies.get('uid')),
24 | zhilian: true,
25 | per: 0
26 | }
27 | }
28 |
29 | componentDidMount() {
30 | if (this.props.location.pathname.indexOf('add-video') > -1) {
31 | this.setState({text: '添加'})
32 | } else {
33 | this.loadVideo()
34 | this.setState({text: '修改'})
35 | }
36 | }
37 |
38 | loadVideo() {
39 | getVideo(this.state.id).then(res => {
40 | if (res.data.code === 200) {
41 | this.setState(res.data.result)
42 | }
43 | })
44 | }
45 |
46 | handleChange(key, val) {
47 | this.setState({
48 | [key]: val
49 | })
50 | }
51 |
52 | deleteVideo() {
53 | deleteVideoById(this.state.id).then(res => {
54 | if (res.data.code === 200) {
55 | this.setState({
56 | msg: '删除成功啦'
57 | })
58 | setTimeout(() => {
59 | this.props.history.goBack()
60 | this.setState({
61 | msg: ''
62 | })
63 | }, 2000)
64 | }
65 | })
66 | }
67 |
68 | handleClick() {
69 | if (this.props.location.pathname.indexOf('editor-video') > -1) {
70 | updateVideo(this.state).then(res => {
71 | if (res.data.code === 200) {
72 | this.setState({
73 | msg: '更新成功啦'
74 | })
75 | }
76 | setTimeout(() => {
77 | this.props.history.goBack()
78 | this.setState({
79 | msg: ''
80 | })
81 | }, 2000)
82 | })
83 | } else {
84 | this.addVideos()
85 | }
86 | }
87 |
88 | addVideos() {
89 | addVideo(this.state).then(res => {
90 | if (res.data.code === 200) {
91 | this.setState({
92 | msg: '添加成功啦'
93 | })
94 | }
95 | setTimeout(() => {
96 | this.props.history.goBack()
97 | this.setState({
98 | msg: ''
99 | })
100 | }, 2000)
101 | })
102 | }
103 |
104 | async onUpload() {
105 | let self = this
106 | let file = this.refs.uploader.files[0]
107 | let rname = this.state.pid + ' | ' + this.state.oid
108 | const token = await getUploadToken(file.name, rname).then(res => {
109 | return res.data.uploadToken
110 | })
111 | console.log(token)
112 | const uploader = new DogeUploader({
113 | file,
114 | token,
115 | next(progress) {
116 | self.setState({
117 | per: `${Math.floor(progress.percent)}`
118 | })
119 | },
120 | error(err) {
121 | alert('上传出错( ' + err.code + ' ):' + err.message + '')
122 | },
123 | complete(res) {
124 | console.log('上传完成,视频 vid:' + res.vid)
125 | self.setState({
126 | content: `${res.vid}@dogecloud`,
127 | per: 0
128 | })
129 | }
130 | })
131 |
132 | uploader.upload()
133 | }
134 |
135 | zhilian() {
136 | this.setState({
137 | zhilian: !this.state.zhilian
138 | })
139 | }
140 |
141 | render() {
142 | return (
143 |
144 | {this.state.msg ?
: null}
145 | {this.state.per ?
{this.state.per + '%'}
: null}
146 |
147 |
148 |
{this.state.text}视频
149 |
170 |
171 |
172 | )
173 | }
174 | }
175 |
176 | export default EditorVideo
--------------------------------------------------------------------------------
/packages/react/src/component/header/header.css:
--------------------------------------------------------------------------------
1 |
2 | header {
3 | background: #7e5fd9;
4 | padding: 10px;
5 | width: 100%;
6 | position: fixed;
7 | top: 0;
8 | z-index: 9;
9 | }
10 |
11 | header li {
12 | display: inline-block;
13 | color: #fff;
14 | padding: 10px 30px;
15 | cursor: pointer;
16 | position: relative;
17 | }
18 |
19 | header li:hover {
20 | background: #6c43b6;
21 | }
22 |
23 | header li:hover ul {
24 | display: block;
25 | position: absolute;
26 | top: 38px;
27 | left: 0;
28 | white-space: nowrap;
29 | background: #6c43b6;
30 | padding: 10px 0 15px 0;
31 | }
32 |
33 | header li:hover ul li {
34 | display: block;
35 | font-size: 13px;
36 | }
37 |
38 | header li:hover ul li:hover {
39 | font-weight: bold;
40 | }
41 |
42 | header li ul {
43 | display: none;
44 | }
45 |
46 | header .logout {
47 | background: #9579e8;
48 | float: right;
49 | border-right: 1px solid #7e5fd9;
50 | }
51 |
52 | header .logout:hover {
53 | background: #9579e8;
54 | font-weight: bold;
55 | }
56 |
57 |
58 |
--------------------------------------------------------------------------------
/packages/react/src/component/header/header.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | import {Link, withRouter} from 'react-router-dom'
4 | import {HOME_LINK} from "common/js/util"
5 | import {adminAuth} from "hoc/auth/auth"
6 | import {map} from "smox"
7 | import {logout} from "api/user"
8 |
9 | import './header.css'
10 |
11 | @map({
12 | state: ['redirectTo'],
13 | mutations: ['logout']
14 | })
15 | @withRouter
16 | @adminAuth
17 | class Header extends React.Component {
18 | onLogout() {
19 | this.props.logout()
20 | logout().then(res => {
21 | if (res.data.code === 200) {
22 | this.props.history.push('/login')
23 | }
24 | })
25 |
26 | }
27 |
28 | render() {
29 | return (
30 |
31 |
32 |
33 | - 控制台
34 |
35 | {this.props.state.level >= 2 ?
36 |
37 | - 撰写
38 | : null}
39 | {this.props.state.level >= 3 ?
40 | - 管理
41 |
42 |
43 | - 审核稿件
44 |
45 |
46 | - 管理稿件
47 |
48 |
49 | - 管理用户
50 |
51 |
52 |
53 | : null}
54 | -
55 | 退出
56 |
57 |
58 | -
59 | 网站首页
60 |
61 |
62 |
63 |
64 | )
65 | }
66 |
67 | }
68 |
69 | export default Header
--------------------------------------------------------------------------------
/packages/react/src/component/login/login.css:
--------------------------------------------------------------------------------
1 | .login {
2 | width: 280px;
3 | position: absolute;
4 | top: 50%;
5 | left: 50%;
6 | transform: translate(-50%, -50%);
7 | }
8 |
9 | .login li {
10 | padding: 8px 0;
11 | text-align: center;
12 | }
13 |
14 | .login li input {
15 | padding: 10px;
16 | width: 100%;
17 | box-sizing: border-box;
18 | box-shadow: 1px 1px 1px rgba(70, 75, 150, 0.2);
19 | border: 0px;
20 | }
21 |
22 | .login li button{
23 | background: #7e5fd9;
24 | width: 100%;
25 | border: 0px;
26 | box-shadow: 1px 1px 1px rgba(60, 32, 105, 0.6);
27 | padding: 10px;
28 | color: #fff;
29 | cursor: pointer;
30 | }
31 | .login li a{
32 | text-align: center;
33 | }
34 |
35 | .login h1{
36 | color: #7e5fd9;
37 | font-size: 40px;
38 | padding: 10px;
39 | }
--------------------------------------------------------------------------------
/packages/react/src/component/login/login.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | import {Link, withRouter} from 'react-router-dom'
4 |
5 | import {map} from 'smox'
6 | import {handleForm} from "hoc/handle-form/handle-form"
7 | import TopTip from 'base/top-tip/top-tip'
8 |
9 | import './login.css'
10 |
11 | @map({
12 | state: ['isAuth', 'msg', 'bg'],
13 | actions: ['onLogin']
14 | })
15 | @handleForm
16 | @withRouter
17 | class Login extends React.Component {
18 |
19 | onKeyUp(e) {
20 | if (e.keyCode === 13) {
21 | this.onLogin()
22 | }
23 | }
24 |
25 | onLogin() {
26 | this.props.onLogin(this.props.state)
27 | }
28 |
29 | render() {
30 | return (
31 |
32 | {this.props.isAuth ? setTimeout(() => {
33 | this.props.history.push('/')
34 | }, 2000) : null}
35 | {this.props.msg ?
: null}
36 |
37 |
50 |
51 | )
52 | }
53 | }
54 |
55 | export default Login
--------------------------------------------------------------------------------
/packages/react/src/component/post-list/post-list.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {getPosts} from 'api/post'
3 | import ListView from '../../base/list-view/list-view'
4 | import {withRouter, Link} from 'react-router-dom'
5 |
6 | import ReachBox from 'base/reach-box/reach-box'
7 |
8 |
9 | @withRouter
10 | class PostList extends React.Component {
11 | constructor(props) {
12 | super(props)
13 | this.state = {
14 | posts: []
15 | }
16 | }
17 |
18 | loadArticles() {
19 | let status = this.props.match.params.status
20 | getPosts(status, '', '', '', 1, 100).then((res) => {
21 | if (res.data.code === 200) {
22 | this.setState({
23 | posts: res.data.posts
24 | })
25 | }
26 | })
27 | }
28 |
29 | loadAuthorArticle() {
30 | getPosts('', '', '', this.props.match.params.author, 1, 100).then(res => {
31 | if (res.data.code === 200) {
32 | this.setState({
33 | posts: res.data.posts
34 | })
35 | }
36 | })
37 | }
38 |
39 | refresh() {
40 | let p = this.props.location.pathname
41 | if (p === '/posts/wait' || p === '/posts/public' || p === '/posts/under') {
42 | return this.loadArticles()
43 | }
44 | this.loadAuthorArticle()
45 | }
46 |
47 | render() {
48 | return (
49 |
50 |
51 | 待审核
52 | 已下架
53 | 已发布
54 |
55 |
56 | )
57 | }
58 |
59 | componentDidMount() {
60 | this.refresh()
61 | }
62 | }
63 |
64 | export default PostList
--------------------------------------------------------------------------------
/packages/react/src/component/register/register.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {register} from "api/user"
3 | import {handleForm} from "hoc/handle-form/handle-form"
4 |
5 | import TopTip from '../../base/top-tip/top-tip'
6 | import '../login/login.css'
7 |
8 | @handleForm
9 | class Home extends React.Component {
10 | constructor(props) {
11 | super(props)
12 | this.state = {
13 | msg: '',
14 | bg: ''
15 | }
16 |
17 | this.onRegister = this.onRegister.bind(this)
18 |
19 | }
20 |
21 | onRegister() {
22 | if (!this.props.state.name || !this.props.state.pwd || !this.props.state.repeatPwd || !this.props.state.qq) {
23 | this.setState({
24 | msg: '都要填写都要填(〃>皿<)!',
25 | bg: '#ef736e'
26 | })
27 | setTimeout(() => {
28 | this.setState({
29 | msg: ''
30 | })
31 | }, 4500)
32 | return
33 | }
34 | register(this.props.state).then(res => {
35 | if (res.status === 200 && res.data.code === 201) {
36 | this.setState({
37 | msg: res.data.msg,
38 | bg: '#b4d896'
39 | })
40 | setTimeout(() => {
41 | this.props.history.push('/login')
42 | }, 2000)
43 | } else {
44 | this.setState({
45 | msg: res.data.msg,
46 | bg: '#ef736e'
47 | })
48 | }
49 | })
50 |
51 | }
52 |
53 | onKeyUp(e) {
54 | if (e.keyCode === 13) {
55 | this.onRegister()
56 | }
57 | }
58 |
59 | render() {
60 | return (
61 |
62 | {this.state.msg ?
: null}
63 |
64 |
84 |
85 | )
86 | }
87 | }
88 |
89 | export default Home
--------------------------------------------------------------------------------
/packages/react/src/component/user-info/user-info.css:
--------------------------------------------------------------------------------
1 | .user-info {
2 | padding: 200px 0;
3 | }
4 |
5 | .user-info .avatar {
6 | text-align: center;
7 | padding-bottom: 30px;
8 |
9 | }
10 |
11 | .avatar img {
12 | height: 60px;
13 | width: 60px;
14 | border-radius: 50%;
15 | }
16 |
17 | .name {
18 | text-align: center;
19 | font-weight: bold;
20 | font-size: 16px;
21 | }
22 |
23 | .uid {
24 | text-align: center;
25 | font-weight: bold;
26 | font-size: 16px;
27 | color: #fff;
28 | margin-top: 10px;
29 | }
30 |
31 | .uid span{
32 | background: #6c43b6;
33 | padding: 0px 15px;
34 | }
35 |
36 | .quick-start {
37 | padding: 100px;
38 | color: #999;
39 | text-align: center;
40 | }
41 |
42 | .quick-start span {
43 | color: #7e5fd9;
44 | padding: 10px;
45 | }
--------------------------------------------------------------------------------
/packages/react/src/component/user-info/user-info.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | import { Link } from 'react-router-dom'
4 | import { adminAuth } from "hoc/auth/auth"
5 | import { getUser } from 'api/user'
6 | import { getAvatar } from "common/js/util"
7 |
8 | import './user-info.css'
9 | import Cookies from "js-cookie"
10 |
11 | @adminAuth
12 | class UserInfo extends React.Component {
13 | constructor(props) {
14 | super(props)
15 | this.state = {
16 | user: {
17 | qq: 10010,
18 | name:'emmm',
19 | id:2
20 | }
21 | }
22 | }
23 |
24 | componentDidMount() {
25 | const uid = Cookies.get('uid') || "2"
26 | if (uid) {
27 | getUser('', uid).then(res => {
28 | this.setState({
29 | user: res.data.result
30 | })
31 | })
32 | }
33 | }
34 |
35 | render() {
36 | const qq = getAvatar(this.state.user.qq)
37 | const router = `/article/` + this.state.user.id
38 | const info = `/editor-user/` + this.state.user.qq
39 | return (
40 |
41 |
42 |

43 |
44 |
欢迎!{this.state.user.name} sama~
45 |
uid : {this.state.user.id}
46 |
47 | 快速开始:
48 | {this.props.state.level > 1 ?
49 | 投稿
50 | : null}
51 | {this.props.state.level > 1 ? 查看稿件 : null}
52 | 设置
53 |
54 |
55 | )
56 | }
57 | }
58 |
59 | export default UserInfo
--------------------------------------------------------------------------------
/packages/react/src/component/user-list/user-list.css:
--------------------------------------------------------------------------------
1 | .user-list {
2 | width: 900px;
3 | margin: 50px auto;
4 | }
5 |
6 | .user-list .role {
7 | margin-bottom: 20px;
8 | }
9 |
10 | .user-list h1 {
11 | color: #7e5fd9;
12 | font-size: 24px;
13 | padding: 10px;
14 | margin-bottom: 20px;
15 | }
16 |
17 | .user-list ul {
18 | display: flex;
19 | padding: 20px;
20 | box-shadow: 0 1px 0 rgba(70, 75, 150, 0.2);
21 | background: #fff;
22 | flex-wrap: wrap;
23 | }
24 |
25 | .user-list ul li {
26 | flex: 1;
27 | padding: 20px;
28 | }
29 |
30 | .user-list .avatar {
31 | padding-bottom: 10px;
32 | text-align: center;
33 | border-radius: 50%;
34 | }
35 |
36 | .user-list .avatar img {
37 | height: 100px;
38 | width: 100px;
39 | }
40 |
41 |
42 |
--------------------------------------------------------------------------------
/packages/react/src/component/user-list/user-list.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | import {userList} from 'api/user'
4 | import {Link, withRouter} from 'react-router-dom'
5 | import ReachBox from 'base/reach-box/reach-box'
6 |
7 | import './user-list.css'
8 |
9 | @withRouter
10 | class UserList extends React.Component {
11 | constructor(props) {
12 | super(props)
13 | this.state = {
14 | users: [],
15 | uid: ''
16 | }
17 | }
18 |
19 | componentDidMount() {
20 | userList(this.props.match.params.level).then((res) => {
21 | if (res.data.code === 200) {
22 | this.setState({users: res.data.users})
23 | }
24 | })
25 | }
26 |
27 | render() {
28 |
29 | return (
30 |
31 |
32 | 用户
33 | 作者
34 | 审核
35 |
36 |
37 |
38 | {this.props.location.pathname === '/users/user' ?
39 |
40 | :
41 | this.state.users.map((item) => {
42 | const qq = `http://q2.qlogo.cn/headimg_dl?dst_uin=` + item.qq + `&spec=100`
43 | return (
44 | -
45 |
46 |
47 |
{item.name}
48 |
49 |
50 | )
51 | })}
52 |
53 |
54 |
55 | )
56 | }
57 | }
58 |
59 | export default UserList
--------------------------------------------------------------------------------
/packages/react/src/component/write-article/wirte-article.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { add, getPost, update } from 'api/post'
3 | import { getVideos } from "api/video"
4 | import { adminAuth } from "hoc/auth/auth"
5 | import { Link } from 'react-router-dom'
6 | import Cookies from 'js-cookie'
7 |
8 | import Markdown from 'base/markdown/markdown'
9 | import TopTip from 'base/top-tip/top-tip'
10 |
11 | import './write-article.css'
12 |
13 | @adminAuth
14 | class WriteArticle extends React.Component {
15 | constructor(props) {
16 |
17 | super(props)
18 | this.state = {
19 | title: '',
20 | content: '',
21 | sort: '完结',
22 | status: 'wait',
23 | msg: '',
24 | uid: parseInt(Cookies.get('uid')),
25 | id: this.props.match.params.editor,
26 | text: '撰写',
27 | bg: '',
28 | tag: '',
29 | time: '',
30 | videos: []
31 | }
32 | }
33 |
34 | componentDidMount() {
35 | this.loadArticle()
36 | this.props.location.pathname === '/write-article' ? this.setState({ text: '添加' }) : this.setState({ text: '更新' })
37 | }
38 |
39 | handleChange(key, val) {
40 | this.setState({
41 | [key]: val
42 | })
43 | }
44 |
45 | changeMde(content) {
46 | this.setState({
47 | content
48 | })
49 | }
50 |
51 | loadArticle() {
52 | if (this.state.id) {
53 | getPost(this.state.id).then((res) => {
54 | const { title, content, sort, tag, status, time, videos } = res.data.result
55 | this.setState({
56 | title,
57 | content,
58 | sort,
59 | tag,
60 | status,
61 | time: time.slice(0, -3),
62 | videos,
63 | defaultValue: content
64 | })
65 | })
66 | }
67 | }
68 |
69 | handleClick() {
70 | if (!this.state.title || !this.state.content || !this.state.status || !this.state.sort || !this.state.tag) {
71 | this.setState({
72 | msg: '都要填写都要填(〃>皿<)!',
73 | bg: '#ef736e'
74 | })
75 | setTimeout(() => {
76 | this.setState({
77 | msg: ''
78 | })
79 | }, 5000)
80 | return
81 | }
82 |
83 | if (this.props.location.pathname !== '/write-article') {
84 | update(this.state).then((res) => {
85 | if (res.data.code === 200) {
86 | this.setState({
87 | msg: '更新成功啦!',
88 | text: '更新',
89 | bg: '#b4d896'
90 | })
91 | }
92 | setTimeout(() => {
93 | this.props.history.push(`/article/${this.state.uid}`)
94 | this.setState({
95 | msg: ''
96 | })
97 | }, 5000)
98 | })
99 | } else {
100 | add(this.state).then((res) => {
101 | if (res.data.code === 200) {
102 | this.setState({
103 | msg: '添加成功啦',
104 | bg: '#b4d896'
105 | })
106 | }
107 | setTimeout(() => {
108 | this.props.history.push(`/article/${this.state.uid}`)
109 | this.setState({
110 | msg: ''
111 | })
112 | }, 5000)
113 | })
114 | }
115 | }
116 |
117 | selectTag(item) {
118 | if (this.state.tag.indexOf(item) > -1) {
119 | this.setState({
120 | tag: this.state.tag.replace(` ${item}`, '')
121 | })
122 | } else {
123 | this.setState({
124 | tag: this.state.tag + ' ' + item
125 | })
126 | }
127 | }
128 |
129 | render() {
130 | const tags = ['推荐', '转载', '漫画改', '小说改', '耽美', '乙女', '百合', '后宫', '热血', '战斗', '运动', '奇幻', '神魔',
131 | '搞笑', '冒险', '校园', '恐怖', '穿越', '推理', '科幻', '日常', '古风', '恋爱', 'r15', '泡面番', '治愈',
132 | '鬼畜', 'AMV/MAD', '音乐·PV', '游戏·GMV', 'VOCALOID', '影视',
133 | '特摄', '真人剧', '其它']
134 | return (
135 | {this.state.msg ?
: null}
136 |
137 |
{this.state.text}稿件
138 |
this.handleChange('title', e.target.value)} />
141 |
this.changeMde(content)}
142 | value={this.state.content} defaultValue={this.state.defaultValue} />
143 |
149 |
150 |
158 |
166 | {this.props.location.pathname === '/write-article' ? null : this.handleChange('time', e.target.value)} />}
168 |
169 |
170 | {tags.map((item, index) => - this.selectTag(item)} key={index}
171 | className={this.state.tag.indexOf(item) > -1 ? 'active' : ''}>{item}
)}
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 | )
181 | }
182 | }
183 |
184 |
185 | export default WriteArticle
--------------------------------------------------------------------------------
/packages/react/src/component/write-article/write-article.css:
--------------------------------------------------------------------------------
1 | .write-article {
2 | width: 800px;
3 | margin: 100px auto;
4 | }
5 |
6 | .write-article h1 {
7 | color: #7e5fd9;
8 | font-size: 24px;
9 | margin: 20px 0;
10 | }
11 |
12 | .write-article li input {
13 | padding: 10px;
14 | width: 100%;
15 | box-shadow: 1px 1px 1px rgba(70, 75, 150, 0.2);
16 | border: 0;
17 | margin: 10px 0;
18 | box-sizing: border-box;
19 | }
20 | .write-article span input {
21 | padding: 4px 10px;
22 | border: 0;
23 | background: #ffeec7;
24 | box-sizing: border-box;
25 | border-radius: 4px;
26 | outline: none;
27 | }
28 | .write-article button {
29 | background: #7e5fd9;
30 | padding: 8px 30px;
31 | color: #fff;
32 | margin: 20px 0;
33 | border: 0;
34 | box-shadow: 1px 1px 1px rgba(70, 75, 150, 0.6);
35 | cursor: pointer;
36 | float: right;
37 | }
38 |
39 | .write-article select {
40 | padding: 5px 17px;
41 | box-shadow: 1px 1px 1px rgba(70, 75, 150, 0.2);
42 | border: 0;
43 | color: #666;
44 | margin: 20px 20px 20px 0;
45 | position: relative;
46 | top: 3px;
47 | }
48 |
49 | .write-article span {
50 | color: #666;
51 | font-size: 13px;
52 | }
53 |
54 | .write-article .video-list li {
55 | height: 40px;
56 | width: 40px;
57 | text-align: center;
58 | background: #fff;
59 | list-style: none;
60 | display: inline-block;
61 | margin: 10px 15px 0 0;
62 | padding: 10px;
63 | box-sizing: border-box;
64 | border-radius: 50%;
65 | border: 1px solid #7e5fd9;
66 | }
67 |
68 | .write-article .video-list .add {
69 | font-weight: bold;
70 | background: #7e5fd9;
71 | color: #fff;
72 | }
73 |
74 | .write-article .video-list .add div {
75 | position: relative;
76 | top: -2px;
77 | }
78 |
79 | .write-article .tags {
80 | padding-bottom: 20px;
81 | }
82 |
83 | .write-article .videos-area{
84 | white-space: pre;
85 | word-wrap: break-word;
86 | overflow: scroll;
87 | outline: none;
88 | }
89 |
90 | .write-article .tags li {
91 | display: inline-block;
92 | padding: 2px 10px;
93 | background: #e0d8f7;;
94 | color: #6c43b6;
95 | border-radius: 4px;
96 | margin: 10px 10px 0 0;
97 | cursor: pointer;
98 | }
99 |
100 | .write-article .tags .active {
101 | background: #6c43b6;
102 | color: #fff;
103 | }
104 |
105 |
--------------------------------------------------------------------------------
/packages/react/src/hoc/auth/auth.js:
--------------------------------------------------------------------------------
1 | import React from "react"
2 | import {API_LINK} from "common/js/util"
3 | import {auth} from 'api/user'
4 | import Cookies from 'js-cookie'
5 |
6 | export function adminAuth(Component) {
7 | return class WrapperComp extends React.Component {
8 | constructor(props) {
9 | super(props)
10 | this.state = {
11 | level: 1
12 | }
13 | }
14 |
15 | componentDidMount() {
16 | auth().then(res => {
17 | if (res.data.code === 401) {
18 | this.props.history.push('/login')
19 | } else {
20 | this.setState({
21 | level: Cookies.get('level')
22 | })
23 | }
24 | })
25 | }
26 |
27 | render() {
28 | return
29 | }
30 | }
31 | }
--------------------------------------------------------------------------------
/packages/react/src/hoc/handle-form/handle-form.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | // 表单提交公共方法
4 | export function handleForm(Component) {
5 | return class WrapperComp extends React.Component {
6 | constructor(props) {
7 | super(props)
8 | this.state = {}
9 | this.handleChange = this.handleChange.bind(this)
10 | }
11 |
12 | handleChange(key, val) {
13 | this.setState({
14 | [key]: val
15 | })
16 | }
17 |
18 | render() {
19 | return
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/packages/react/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | clicli后台
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/packages/react/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ReactDom from 'react-dom'
3 | import {BrowserRouter} from 'react-router-dom'
4 |
5 |
6 | import App from './app'
7 |
8 | import './common/style/reset.css'
9 | import './common/style/index.css'
10 | import './common/style/iconfont.css'
11 |
12 | import {store} from './store/index'
13 | import {Provider} from 'smox'
14 |
15 |
16 | ReactDom.render((
17 |
18 |
19 |
20 |
21 |
22 |
23 | ), document.getElementById('app'))
24 |
25 |
--------------------------------------------------------------------------------
/packages/react/src/store/actions.js:
--------------------------------------------------------------------------------
1 | import {login, logout} from "api/user"
2 |
3 | export default {
4 | onLogin({commit}, user) {
5 | if (!user.name || !user.pwd) {
6 | commit('errMsg', '都要填都要填!')
7 | setTimeout(() => {
8 | commit('errMsg', '')
9 | }, 4500)
10 | }
11 | return login(user).then(res => {
12 | commit('errMsg', '')
13 | if (res.status === 200) {
14 | commit('login', res.data)
15 | } else {
16 | commit('errMsg', res.data.msg)
17 | setTimeout(() => {
18 | commit('errMsg', '')
19 | }, 4500)
20 | }
21 | })
22 | },
23 | onLogout({commit}) {
24 | return logout().then(res => {
25 | if (res.data.code === 200) {
26 | commit('logout', res.data)
27 | setTimeout(() => {
28 | commit('errMsg', '')
29 | }, 4500)
30 | }
31 | })
32 | }
33 |
34 | }
--------------------------------------------------------------------------------
/packages/react/src/store/index.js:
--------------------------------------------------------------------------------
1 | import { Store } from 'smox'
2 | import state from './state'
3 | import mutations from './mutations'
4 | import actions from './actions'
5 |
6 | export const store = new Store({
7 | state,
8 | mutations,
9 | actions
10 | })
11 |
--------------------------------------------------------------------------------
/packages/react/src/store/mutations.js:
--------------------------------------------------------------------------------
1 | export default {
2 | login(state, data) {
3 | state.msg = data.msg
4 | state.isAuth = true
5 | state.bg = '#b4d896'
6 | },
7 | errMsg(state, msg) {
8 | state.msg = msg
9 | state.bg = '#ef736e'
10 | },
11 | logout(state) {
12 | state.isAuth = false
13 | state.msg = '退出成功啦'
14 | state.bg = '#b4d896'
15 | }
16 | }
--------------------------------------------------------------------------------
/packages/react/src/store/state.js:
--------------------------------------------------------------------------------
1 | export default {
2 | isAuth: false,
3 | redirectTo: '',
4 | bg: '',
5 | msg: '',
6 | user:{}
7 | }
8 |
--------------------------------------------------------------------------------
/packages/react/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 | const HtmlWebpackPlugin = require('html-webpack-plugin')
3 | const MiniCssExtractPlugin = require("mini-css-extract-plugin")
4 | const webpack = require('webpack')
5 |
6 | module.exports = {
7 | entry: './src/index.js',
8 | output: {
9 | path: path.resolve(__dirname, 'dist'),
10 | filename: '[name].js',
11 | publicPath:'/'
12 | },
13 | resolve: {
14 | alias: {
15 | component: path.resolve(__dirname, 'src/component'),
16 | common: path.resolve(__dirname, 'src/common'),
17 | api: path.resolve(__dirname, 'src/api'),
18 | base: path.resolve(__dirname, 'src/base'),
19 | store: path.resolve(__dirname, 'src/store'),
20 | hoc: path.resolve(__dirname, 'src/hoc')
21 | }
22 | },
23 | module: {
24 | rules: [
25 | {
26 | test: /\.js$/,
27 | exclude: /node_modules/,
28 | use: {
29 | loader: 'babel-loader'
30 | }
31 | },
32 | {
33 | test: /\.css$/,
34 | use: [
35 | MiniCssExtractPlugin.loader,
36 | "css-loader"
37 | ]
38 |
39 | },
40 | {
41 | test: /\.(png|jpg|gif)$/,
42 | use: [
43 | {
44 | loader: 'url-loader',
45 | options: {
46 | limit: 8192,
47 | name: 'static/img/[name].[ext]'
48 | }
49 | }
50 | ]
51 | }
52 | ]
53 | },
54 | optimization: {
55 | splitChunks: {
56 | chunks: 'all'
57 | },
58 | runtimeChunk: false,
59 | minimize:false
60 | },
61 | plugins: [
62 | new webpack.HotModuleReplacementPlugin(),
63 | new HtmlWebpackPlugin({
64 | template: './src/index.html'
65 | }),
66 | new MiniCssExtractPlugin({
67 | filename: "[name].css"
68 | }),
69 | ],
70 | devServer: {
71 | headers: {'Access-Control-Allow-Origin': '*'},
72 | contentBase: path.join(__dirname, "dist"),
73 | compress: true,
74 | port: 1122,
75 | historyApiFallback: true,
76 | hot: true,
77 | proxy: {
78 | '/api/*': {
79 | pathRewrite: {'^/api': ''},
80 | target: 'https://api.clicli.cc'
81 | }
82 | }
83 | }
84 | }
--------------------------------------------------------------------------------
/pnpm-lock.yaml:
--------------------------------------------------------------------------------
1 | lockfileVersion: 5.3
2 |
3 | importers:
4 |
5 | .:
6 | specifiers:
7 | react: ^0.0.0-experimental-1314299c7-20210901
8 | react-dom: ^0.0.0-experimental-1314299c7-20210901
9 | dependencies:
10 | react: 0.0.0-experimental-1314299c7-20210901
11 | react-dom: 0.0.0-experimental-1314299c7-20210901_e51ce3ac058c0d2f1ad274f789274e97
12 |
13 | packages/create-nfes:
14 | specifiers:
15 | '@ctrip/nfes': workspace:^1.0.0
16 | dependencies:
17 | '@ctrip/nfes': link:../nfes
18 |
19 | packages/nfes:
20 | specifiers:
21 | '@types/node': ^16.7.12
22 | esbuild: ^0.12.25
23 | esbuild-register: ^3.0.0
24 | fs-extra: ^10.0.0
25 | polka: ^0.5.2
26 | dependencies:
27 | fs-extra: 10.0.0
28 | polka: 0.5.2
29 | devDependencies:
30 | '@types/node': 16.7.12
31 | esbuild: 0.12.25
32 | esbuild-register: 3.0.0_esbuild@0.12.25
33 |
34 | packages:
35 |
36 | /@arr/every/1.0.1:
37 | resolution: {integrity: sha512-UQFQ6SgyJ6LX42W8rHCs8KVc0JS0tzVL9ct4XYedJukskYVWTo49tNiMEK9C2HTyarbNiT/RVIRSY82vH+6sTg==}
38 | engines: {node: '>=4'}
39 | dev: false
40 |
41 | /@polka/url/0.5.0:
42 | resolution: {integrity: sha512-oZLYFEAzUKyi3SKnXvj32ZCEGH6RDnao7COuCVhDydMS9NrCSVXhM79VaKyP5+Zc33m0QXEd2DN3UkU7OsHcfw==}
43 | dev: false
44 |
45 | /@types/node/16.7.12:
46 | resolution: {integrity: sha512-IrhrusVM9QJAn1xLFFqbZH+XCI8L6eZoVHjR4sZeGTBBvjQSuchXGgKpown1jP75TCMSndcbudYBDTekOhcIZA==}
47 | dev: true
48 |
49 | /esbuild-register/3.0.0_esbuild@0.12.25:
50 | resolution: {integrity: sha512-No7U3ZUd6gPrrC6gqdb3XFcf2lNqzn8nvQXcgcyOl8szMVuN6YUvOplnmakxWyogI9d8SiJMl0uzBzJck+Aoxw==}
51 | peerDependencies:
52 | esbuild: '>=0.12 <1'
53 | dependencies:
54 | esbuild: 0.12.25
55 | jsonc-parser: 3.0.0
56 | dev: true
57 |
58 | /esbuild/0.12.25:
59 | resolution: {integrity: sha512-woie0PosbRSoN8gQytrdCzUbS2ByKgO8nD1xCZkEup3D9q92miCze4PqEI9TZDYAuwn6CruEnQpJxgTRWdooAg==}
60 | hasBin: true
61 | requiresBuild: true
62 | dev: true
63 |
64 | /fs-extra/10.0.0:
65 | resolution: {integrity: sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==}
66 | engines: {node: '>=12'}
67 | dependencies:
68 | graceful-fs: 4.2.8
69 | jsonfile: 6.1.0
70 | universalify: 2.0.0
71 | dev: false
72 |
73 | /graceful-fs/4.2.8:
74 | resolution: {integrity: sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==}
75 | dev: false
76 |
77 | /js-tokens/4.0.0:
78 | resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
79 | dev: false
80 |
81 | /jsonc-parser/3.0.0:
82 | resolution: {integrity: sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==}
83 | dev: true
84 |
85 | /jsonfile/6.1.0:
86 | resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==}
87 | dependencies:
88 | universalify: 2.0.0
89 | optionalDependencies:
90 | graceful-fs: 4.2.8
91 | dev: false
92 |
93 | /loose-envify/1.4.0:
94 | resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
95 | hasBin: true
96 | dependencies:
97 | js-tokens: 4.0.0
98 | dev: false
99 |
100 | /matchit/1.1.0:
101 | resolution: {integrity: sha512-+nGYoOlfHmxe5BW5tE0EMJppXEwdSf8uBA1GTZC7Q77kbT35+VKLYJMzVNWCHSsga1ps1tPYFtFyvxvKzWVmMA==}
102 | engines: {node: '>=6'}
103 | dependencies:
104 | '@arr/every': 1.0.1
105 | dev: false
106 |
107 | /object-assign/4.1.1:
108 | resolution: {integrity: sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=}
109 | engines: {node: '>=0.10.0'}
110 | dev: false
111 |
112 | /polka/0.5.2:
113 | resolution: {integrity: sha512-FVg3vDmCqP80tOrs+OeNlgXYmFppTXdjD5E7I4ET1NjvtNmQrb1/mJibybKkb/d4NA7YWAr1ojxuhpL3FHqdlw==}
114 | dependencies:
115 | '@polka/url': 0.5.0
116 | trouter: 2.0.1
117 | dev: false
118 |
119 | /react-dom/0.0.0-experimental-1314299c7-20210901_e51ce3ac058c0d2f1ad274f789274e97:
120 | resolution: {integrity: sha512-hKxIBZb0oZYUoFaDuhcwIG+Xtk/3bkd+Jtuf0KXakKKFGVrPTR77S9sJDW2mTqADDP+5oKHm8vYONE0Ua3z38Q==}
121 | peerDependencies:
122 | react: 0.0.0-experimental-1314299c7-20210901
123 | dependencies:
124 | loose-envify: 1.4.0
125 | object-assign: 4.1.1
126 | react: 0.0.0-experimental-1314299c7-20210901
127 | scheduler: 0.0.0-experimental-1314299c7-20210901
128 | dev: false
129 |
130 | /react/0.0.0-experimental-1314299c7-20210901:
131 | resolution: {integrity: sha512-A7oXsm7J0SerEWEwt5j6No3jDFaWAhgBerhwSWh2Si81opJb4UpgQ8LfgtLoHItK3VFlVySH2WCViKAVbOzbNQ==}
132 | engines: {node: '>=0.10.0'}
133 | dependencies:
134 | loose-envify: 1.4.0
135 | object-assign: 4.1.1
136 | dev: false
137 |
138 | /scheduler/0.0.0-experimental-1314299c7-20210901:
139 | resolution: {integrity: sha512-ZE2wFqqPnGL2d4GRgZ/0AEwBSpg7fHOe+nY5dZFI/RpjDZmKN+13/Yldn/sM5Fz0SyqliqmMy4vQzyb+ndBi5g==}
140 | dependencies:
141 | loose-envify: 1.4.0
142 | object-assign: 4.1.1
143 | dev: false
144 |
145 | /trouter/2.0.1:
146 | resolution: {integrity: sha512-kr8SKKw94OI+xTGOkfsvwZQ8mWoikZDd2n8XZHjJVZUARZT+4/VV6cacRS6CLsH9bNm+HFIPU1Zx4CnNnb4qlQ==}
147 | engines: {node: '>=6'}
148 | dependencies:
149 | matchit: 1.1.0
150 | dev: false
151 |
152 | /universalify/2.0.0:
153 | resolution: {integrity: sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==}
154 | engines: {node: '>= 10.0.0'}
155 | dev: false
156 |
--------------------------------------------------------------------------------
/pnpm-workspace.yaml:
--------------------------------------------------------------------------------
1 | packages:
2 | # all packages in subdirs of packages/ and components/
3 | - 'packages/**'
--------------------------------------------------------------------------------