refactor: remove certd v1 code
|
@ -1,14 +0,0 @@
|
|||
{
|
||||
"extends": "standard",
|
||||
"env": {
|
||||
"mocha": true
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.test.js", "*.spec.js"],
|
||||
"rules": {
|
||||
"no-unused-expressions": "off"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
.vscode/
|
||||
node_modules/
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
yarn.lock
|
||||
package-lock.json
|
||||
/.idea/
|
|
@ -1,29 +0,0 @@
|
|||
{
|
||||
"name": "@certd/certd",
|
||||
"version": "0.3.0",
|
||||
"description": "a ssl cert keeper",
|
||||
"main": "src/index.js",
|
||||
"scripts": {
|
||||
"test": "echo \\\"Error: no test specified\\\" && exit 1"
|
||||
},
|
||||
"type": "module",
|
||||
"author": "Greper",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@certd/acme-client": "^0.3.0",
|
||||
"@certd/api": "^0.3.0",
|
||||
"dayjs": "^1.9.7",
|
||||
"lodash-es": "^4.17.20",
|
||||
"node-forge": "^0.10.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"chai": "^4.2.0",
|
||||
"eslint": "^7.15.0",
|
||||
"eslint-config-standard": "^16.0.2",
|
||||
"eslint-plugin-import": "^2.22.1",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-promise": "^4.2.1",
|
||||
"mocha": "^8.2.1"
|
||||
},
|
||||
"gitHead": "5fbd7742665c0a949333d805153e9b6af91c0a71"
|
||||
}
|
|
@ -1,202 +0,0 @@
|
|||
import acme from '@certd/acme-client'
|
||||
import _ from 'lodash-es'
|
||||
import { util } from '@certd/api'
|
||||
const logger = util.logger
|
||||
export class AcmeService {
|
||||
constructor (store) {
|
||||
this.store = store
|
||||
acme.setLogger((text) => {
|
||||
logger.info(text)
|
||||
})
|
||||
}
|
||||
|
||||
async getAccountConfig (email) {
|
||||
let conf = this.store.get(this.buildAccountPath(email))
|
||||
if (conf == null) {
|
||||
conf = {}
|
||||
} else {
|
||||
conf = JSON.parse(conf)
|
||||
}
|
||||
return conf
|
||||
}
|
||||
|
||||
buildAccountPath (email) {
|
||||
return this.store.buildKey(email, 'account.json')
|
||||
}
|
||||
|
||||
saveAccountConfig (email, conf) {
|
||||
this.store.set(this.buildAccountPath(email), JSON.stringify(conf))
|
||||
}
|
||||
|
||||
async getAcmeClient (email, isTest) {
|
||||
const conf = await this.getAccountConfig(email)
|
||||
if (conf.key == null) {
|
||||
conf.key = await this.createNewKey()
|
||||
this.saveAccountConfig(email, conf)
|
||||
}
|
||||
if (isTest == null) {
|
||||
isTest = process.env.CERTD_MODE === 'test'
|
||||
}
|
||||
const client = new acme.Client({
|
||||
directoryUrl: isTest ? acme.directory.letsencrypt.staging : acme.directory.letsencrypt.production,
|
||||
accountKey: conf.key,
|
||||
accountUrl: conf.accountUrl,
|
||||
backoffAttempts: 20,
|
||||
backoffMin: 5000,
|
||||
backoffMax: 10000
|
||||
})
|
||||
|
||||
if (conf.accountUrl == null) {
|
||||
const accountPayload = { termsOfServiceAgreed: true, contact: [`mailto:${email}`] }
|
||||
await client.createAccount(accountPayload)
|
||||
conf.accountUrl = client.getAccountUrl()
|
||||
this.saveAccountConfig(email, conf)
|
||||
}
|
||||
return client
|
||||
}
|
||||
|
||||
async createNewKey () {
|
||||
const key = await acme.forge.createPrivateKey()
|
||||
return key.toString()
|
||||
}
|
||||
|
||||
async challengeCreateFn (authz, challenge, keyAuthorization, dnsProvider) {
|
||||
logger.info('Triggered challengeCreateFn()')
|
||||
|
||||
/* http-01 */
|
||||
if (challenge.type === 'http-01') {
|
||||
const filePath = `/var/www/html/.well-known/acme-challenge/${challenge.token}`
|
||||
const fileContents = keyAuthorization
|
||||
|
||||
logger.info(`Creating challenge response for ${authz.identifier.value} at path: ${filePath}`)
|
||||
|
||||
/* Replace this */
|
||||
logger.info(`Would write "${fileContents}" to path "${filePath}"`)
|
||||
// await fs.writeFileAsync(filePath, fileContents);
|
||||
} else if (challenge.type === 'dns-01') {
|
||||
/* dns-01 */
|
||||
const dnsRecord = `_acme-challenge.${authz.identifier.value}`
|
||||
const recordValue = keyAuthorization
|
||||
|
||||
logger.info(`Creating TXT record for ${authz.identifier.value}: ${dnsRecord}`)
|
||||
|
||||
/* Replace this */
|
||||
logger.info(`Would create TXT record "${dnsRecord}" with value "${recordValue}"`)
|
||||
|
||||
return await dnsProvider.createRecord({
|
||||
fullRecord: dnsRecord,
|
||||
type: 'TXT',
|
||||
value: recordValue
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function used to remove an ACME challenge response
|
||||
*
|
||||
* @param {object} authz Authorization object
|
||||
* @param {object} challenge Selected challenge
|
||||
* @param {string} keyAuthorization Authorization key
|
||||
* @param recordItem challengeCreateFn create record item
|
||||
* @param dnsProvider dnsProvider
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
async challengeRemoveFn (authz, challenge, keyAuthorization, recordItem, dnsProvider) {
|
||||
logger.info('Triggered challengeRemoveFn()')
|
||||
|
||||
/* http-01 */
|
||||
if (challenge.type === 'http-01') {
|
||||
const filePath = `/var/www/html/.well-known/acme-challenge/${challenge.token}`
|
||||
|
||||
logger.info(`Removing challenge response for ${authz.identifier.value} at path: ${filePath}`)
|
||||
|
||||
/* Replace this */
|
||||
logger.info(`Would remove file on path "${filePath}"`)
|
||||
// await fs.unlinkAsync(filePath);
|
||||
} else if (challenge.type === 'dns-01') {
|
||||
const dnsRecord = `_acme-challenge.${authz.identifier.value}`
|
||||
const recordValue = keyAuthorization
|
||||
|
||||
logger.info(`Removing TXT record for ${authz.identifier.value}: ${dnsRecord}`)
|
||||
|
||||
/* Replace this */
|
||||
logger.info(`Would remove TXT record "${dnsRecord}" with value "${recordValue}"`)
|
||||
await dnsProvider.removeRecord({
|
||||
fullRecord: dnsRecord,
|
||||
type: 'TXT',
|
||||
value: keyAuthorization,
|
||||
record: recordItem
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
async order ({ email, domains, dnsProvider, dnsProviderCreator, csrInfo, isTest }) {
|
||||
const client = await this.getAcmeClient(email, isTest)
|
||||
|
||||
let accountUrl
|
||||
try {
|
||||
accountUrl = client.getAccountUrl()
|
||||
} catch (e) {
|
||||
}
|
||||
|
||||
/* Create CSR */
|
||||
const { commonName, altNames } = this.buildCommonNameByDomains(domains)
|
||||
|
||||
const [key, csr] = await acme.forge.createCsr({
|
||||
commonName,
|
||||
...csrInfo,
|
||||
altNames
|
||||
})
|
||||
if (dnsProvider == null && dnsProviderCreator) {
|
||||
dnsProvider = await dnsProviderCreator()
|
||||
}
|
||||
if (dnsProvider == null) {
|
||||
throw new Error('dnsProvider 不能为空')
|
||||
}
|
||||
/* 自动申请证书 */
|
||||
const crt = await client.auto({
|
||||
csr,
|
||||
email: email,
|
||||
termsOfServiceAgreed: true,
|
||||
challengePriority: ['dns-01'],
|
||||
challengeCreateFn: async (authz, challenge, keyAuthorization) => {
|
||||
return await this.challengeCreateFn(authz, challenge, keyAuthorization, dnsProvider)
|
||||
},
|
||||
challengeRemoveFn: async (authz, challenge, keyAuthorization, recordItem) => {
|
||||
return await this.challengeRemoveFn(authz, challenge, keyAuthorization, recordItem, dnsProvider)
|
||||
}
|
||||
})
|
||||
|
||||
// 保存账号url
|
||||
if (!accountUrl) {
|
||||
try {
|
||||
accountUrl = client.getAccountUrl()
|
||||
this.setAccountUrl(email, accountUrl)
|
||||
} catch (e) {
|
||||
logger.warn('保存accountUrl出错', e)
|
||||
}
|
||||
}
|
||||
/* Done */
|
||||
logger.debug(`CSR:\n${csr.toString()}`)
|
||||
logger.debug(`Certificate:\n${crt.toString()}`)
|
||||
logger.info('证书申请成功')
|
||||
return { key, crt, csr }
|
||||
}
|
||||
|
||||
buildCommonNameByDomains (domains) {
|
||||
if (typeof domains === 'string') {
|
||||
domains = domains.split(',')
|
||||
}
|
||||
if (domains.length === 0) {
|
||||
throw new Error('domain can not be empty')
|
||||
}
|
||||
const ret = {
|
||||
commonName: domains[0]
|
||||
}
|
||||
if (domains.length > 1) {
|
||||
ret.altNames = _.slice(domains, 1)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
}
|
|
@ -1,131 +0,0 @@
|
|||
import { util, Store, dnsProviderRegistry } from '@certd/api'
|
||||
import { AcmeService } from './acme.js'
|
||||
import { FileStore } from './store/file-store.js'
|
||||
import { CertStore } from './store/cert-store.js'
|
||||
import dayjs from 'dayjs'
|
||||
import forge from 'node-forge'
|
||||
|
||||
const logger = util.logger
|
||||
export class Certd {
|
||||
constructor (options) {
|
||||
this.options = options
|
||||
this.email = options.cert.email
|
||||
this.domains = options.cert.domains
|
||||
|
||||
if (!(options.store instanceof Store)) {
|
||||
this.store = new FileStore(options.store || {})
|
||||
}
|
||||
this.certStore = new CertStore({
|
||||
store: this.store,
|
||||
email: options.cert.email,
|
||||
domains: this.domains
|
||||
})
|
||||
this.acme = new AcmeService(this.store)
|
||||
}
|
||||
|
||||
async certApply () {
|
||||
let oldCert
|
||||
try {
|
||||
oldCert = await this.readCurrentCert()
|
||||
} catch (e) {
|
||||
logger.warn('读取cert失败:', e)
|
||||
}
|
||||
|
||||
if (oldCert == null) {
|
||||
logger.info('还未申请过,准备申请新证书')
|
||||
} else {
|
||||
const ret = this.isWillExpire(oldCert.expires, this.options.cert.renewDays)
|
||||
if (!ret.isWillExpire) {
|
||||
logger.info('证书还未过期:', oldCert.expires, ',剩余', ret.leftDays, '天')
|
||||
if (this.options.args.forceCert) {
|
||||
logger.info('准备强制更新证书')
|
||||
} else {
|
||||
logger.info('暂不更新证书')
|
||||
|
||||
oldCert.isNew = false
|
||||
return oldCert
|
||||
}
|
||||
} else {
|
||||
logger.info('即将过期,准备更新证书')
|
||||
}
|
||||
}
|
||||
|
||||
// 执行证书申请步骤
|
||||
return await this.doCertApply()
|
||||
}
|
||||
|
||||
async doCertApply () {
|
||||
const options = this.options
|
||||
const dnsProvider = this.createDnsProvider(options)
|
||||
const cert = await this.acme.order({
|
||||
email: options.cert.email,
|
||||
domains: options.cert.domains,
|
||||
dnsProvider,
|
||||
csrInfo: options.cert.csrInfo,
|
||||
isTest: options.args.test
|
||||
})
|
||||
|
||||
await this.writeCert(cert)
|
||||
const certRet = await this.readCurrentCert()
|
||||
certRet.isNew = true
|
||||
return certRet
|
||||
}
|
||||
|
||||
createDnsProvider (options) {
|
||||
return this.createProviderByType(options.cert.dnsProvider, options.accessProviders)
|
||||
}
|
||||
|
||||
async writeCert (cert) {
|
||||
const newPath = await this.certStore.writeCert(cert)
|
||||
return {
|
||||
realPath: this.certStore.store.getActualKey(newPath),
|
||||
currentPath: this.certStore.store.getActualKey(this.certStore.currentMarkPath)
|
||||
}
|
||||
}
|
||||
|
||||
async readCurrentCert () {
|
||||
const cert = await this.certStore.readCert()
|
||||
if (cert == null) {
|
||||
return null
|
||||
}
|
||||
const { detail, expires } = this.getCrtDetail(cert.crt)
|
||||
const domain = this.certStore.getMainDomain(this.options.cert.domains)
|
||||
return {
|
||||
...cert, detail, expires, domain, domains: this.domains, email: this.email
|
||||
}
|
||||
}
|
||||
|
||||
getCrtDetail (crt) {
|
||||
const pki = forge.pki
|
||||
const detail = pki.certificateFromPem(crt.toString())
|
||||
const expires = detail.validity.notAfter
|
||||
return { detail, expires }
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否过期,默认提前20天
|
||||
* @param expires
|
||||
* @param maxDays
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isWillExpire (expires, maxDays = 20) {
|
||||
if (expires == null) {
|
||||
throw new Error('过期时间不能为空')
|
||||
}
|
||||
// 检查有效期
|
||||
const leftDays = dayjs(expires).diff(dayjs(), 'day')
|
||||
return {
|
||||
isWillExpire: leftDays < maxDays,
|
||||
leftDays
|
||||
}
|
||||
}
|
||||
|
||||
createProviderByType (props, accessProviders) {
|
||||
const { type } = props
|
||||
const Provider = dnsProviderRegistry.get(type)
|
||||
if (Provider == null) {
|
||||
throw new Error('暂不支持此dnsProvider,请先注册该provider:' + type)
|
||||
}
|
||||
return new Provider({ accessProviders, props })
|
||||
}
|
||||
}
|
|
@ -1,127 +0,0 @@
|
|||
import dayjs from 'dayjs'
|
||||
import crypto from 'crypto'
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function md5 (content) {
|
||||
return crypto.createHash('md5').update(content).digest('hex')
|
||||
}
|
||||
export class CertStore {
|
||||
constructor ({ store, email, domains }) {
|
||||
this.store = store
|
||||
this.email = email
|
||||
this.domains = domains
|
||||
this.domain = this.getMainDomain(this.domains)
|
||||
this.safetyDomain = this.getSafetyDomain(this.domain)
|
||||
this.domainDir = this.safetyDomain + '-' + md5(this.getDomainStr(this.domains))
|
||||
// this.domainDir = this.safetyDomain
|
||||
this.certsRootPath = this.store.buildKey(this.email, 'certs')
|
||||
|
||||
this.currentMarkPath = this.store.buildKey(this.certsRootPath, this.domainDir, 'current.json')
|
||||
}
|
||||
|
||||
getMainDomain (domains) {
|
||||
if (domains == null) {
|
||||
return null
|
||||
}
|
||||
if (typeof domains === 'string') {
|
||||
return domains
|
||||
}
|
||||
if (domains.length > 0) {
|
||||
return domains[0]
|
||||
}
|
||||
}
|
||||
|
||||
getDomainStr (domains) {
|
||||
if (domains == null) {
|
||||
return null
|
||||
}
|
||||
if (typeof domains === 'string') {
|
||||
return domains
|
||||
}
|
||||
return domains.join(',')
|
||||
}
|
||||
|
||||
buildNewCertRootPath (dir) {
|
||||
if (dir == null) {
|
||||
dir = dayjs().format('YYYY.MM.DD.HHmmss')
|
||||
}
|
||||
return this.store.buildKey(this.certsRootPath, this.domainDir, dir)
|
||||
}
|
||||
|
||||
formatCert (pem) {
|
||||
pem = pem.replace(/\r/g, '')
|
||||
pem = pem.replace(/\n\n/g, '\n')
|
||||
pem = pem.replace(/\n$/g, '')
|
||||
return pem
|
||||
}
|
||||
|
||||
async writeCert (cert) {
|
||||
const newDir = this.buildNewCertRootPath()
|
||||
|
||||
const crtKey = this.buildKey(newDir, this.safetyDomain + '.crt')
|
||||
const priKey = this.buildKey(newDir, this.safetyDomain + '.key')
|
||||
const csrKey = this.buildKey(newDir, this.safetyDomain + '.csr')
|
||||
await this.store.set(crtKey, this.formatCert(cert.crt.toString()))
|
||||
await this.store.set(priKey, this.formatCert(cert.key.toString()))
|
||||
await this.store.set(csrKey, cert.csr.toString())
|
||||
|
||||
await this.store.set(this.currentMarkPath, JSON.stringify({ latest: newDir }))
|
||||
|
||||
return newDir
|
||||
}
|
||||
|
||||
async readCert (dir) {
|
||||
if (dir == null) {
|
||||
dir = await this.getCurrentDir()
|
||||
}
|
||||
if (dir == null) {
|
||||
return
|
||||
}
|
||||
|
||||
const crtKey = this.buildKey(dir, this.safetyDomain + '.crt')
|
||||
const priKey = this.buildKey(dir, this.safetyDomain + '.key')
|
||||
const csrKey = this.buildKey(dir, this.safetyDomain + '.csr')
|
||||
const crt = await this.store.get(crtKey)
|
||||
if (crt == null) {
|
||||
return null
|
||||
}
|
||||
const key = await this.store.get(priKey)
|
||||
const csr = await this.store.get(csrKey)
|
||||
|
||||
return {
|
||||
crt: this.formatCert(crt),
|
||||
key: this.formatCert(key),
|
||||
csr,
|
||||
crtPath: this.store.getActualKey(crtKey),
|
||||
keyPath: this.store.getActualKey(priKey),
|
||||
certDir: this.store.getActualKey(dir)
|
||||
}
|
||||
}
|
||||
|
||||
buildKey (...keyItem) {
|
||||
return this.store.buildKey(...keyItem)
|
||||
}
|
||||
|
||||
getSafetyDomain (domain) {
|
||||
return domain.replace(/\*/g, '_')
|
||||
}
|
||||
|
||||
async getCurrentDir () {
|
||||
const current = await this.store.get(this.currentMarkPath)
|
||||
if (current == null) {
|
||||
return null
|
||||
}
|
||||
return JSON.parse(current).latest
|
||||
}
|
||||
|
||||
async getCurrentFile (file) {
|
||||
const currentDir = await this.getCurrentDir()
|
||||
const key = this.buildKey(currentDir, file)
|
||||
return this.store.get(key)
|
||||
}
|
||||
|
||||
async setCurrentFile (file, value) {
|
||||
const currentDir = await this.getCurrentDir()
|
||||
const key = this.buildKey(currentDir, file)
|
||||
return this.store.set(key, value)
|
||||
}
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
import { Store, util } from '@certd/api'
|
||||
import path from 'path'
|
||||
import fs from 'fs'
|
||||
const logger = util.logger
|
||||
export class FileStore extends Store {
|
||||
constructor (opts) {
|
||||
super()
|
||||
if (opts.rootDir != null) {
|
||||
this.rootDir = opts.rootDir
|
||||
} else {
|
||||
this.rootDir = util.path.getUserBasePath()
|
||||
}
|
||||
if (opts.test) {
|
||||
this.rootDir = path.join(this.rootDir, '/test/')
|
||||
}
|
||||
}
|
||||
|
||||
getActualKey (key) {
|
||||
// return 前缀+key
|
||||
return this.getPathByKey(key)
|
||||
}
|
||||
|
||||
buildKey (...keyItem) {
|
||||
return path.join(...keyItem)
|
||||
}
|
||||
|
||||
getPathByKey (key) {
|
||||
return path.join(this.rootDir, key)
|
||||
}
|
||||
|
||||
set (key, value) {
|
||||
const filePath = this.getPathByKey(key)
|
||||
const dir = path.dirname(filePath)
|
||||
if (!fs.existsSync(dir)) {
|
||||
fs.mkdirSync(dir, { recursive: true })
|
||||
}
|
||||
fs.writeFileSync(filePath, value)
|
||||
return filePath
|
||||
}
|
||||
|
||||
get (key) {
|
||||
const filePath = this.getPathByKey(key)
|
||||
if (!fs.existsSync(filePath)) {
|
||||
return null
|
||||
}
|
||||
return fs.readFileSync(filePath).toString()
|
||||
}
|
||||
|
||||
link (targetPath, linkPath) {
|
||||
targetPath = this.getPathByKey(targetPath)
|
||||
linkPath = this.getPathByKey(linkPath)
|
||||
if (fs.existsSync(linkPath)) {
|
||||
try {
|
||||
fs.unlinkSync(linkPath)
|
||||
} catch (e) {
|
||||
logger.error('unlink error:', e)
|
||||
}
|
||||
}
|
||||
fs.symlinkSync(targetPath, linkPath, 'dir')
|
||||
}
|
||||
|
||||
unlink (linkPath) {
|
||||
linkPath = this.getPathByKey(linkPath)
|
||||
fs.unlinkSync(linkPath)
|
||||
}
|
||||
}
|
|
@ -1,88 +0,0 @@
|
|||
import chai from 'chai'
|
||||
import { Certd } from '../src/index.js'
|
||||
import { createOptions } from '../../../../test/options.js'
|
||||
const { expect } = chai
|
||||
const fakeCrt = `-----BEGIN CERTIFICATE-----
|
||||
MIIFSTCCBDGgAwIBAgITAPoZZk/LhVIyXoic2NnJyxubezANBgkqhkiG9w0BAQsF
|
||||
ADAiMSAwHgYDVQQDDBdGYWtlIExFIEludGVybWVkaWF0ZSBYMTAeFw0yMDEyMTQx
|
||||
NjA1NTFaFw0yMTAzMTQxNjA1NTFaMBsxGTAXBgNVBAMMECouZG9jbWlycm9yLmNs
|
||||
dWIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC75tGrYjly+RpcZehQ
|
||||
my1EpaXElT4L60pINKV2YDKnBrcSSo1c6rO7nFh12eC/ju4WwYUep0RVmBDF8xD0
|
||||
I1Sd1uuDTQWP0UT1X9yqdXtjvxpUqoCHAzG633f3sJRFul7mDLuC9tRCuae9o7qP
|
||||
EZ827XOmjBR35dso9I2GEE4828J3YE3tSKtobZlM+30jozLEcsO0PTyM5mq5PPjP
|
||||
VI3fGLcEaBmLZf5ixz4XkcY9IAhyAMYf03cT2wRoYPBaDdXblgCYL6sFtIMbzl3M
|
||||
Di94PB8NyoNSsC2nmBdWi54wFOgBvY/4ljsX/q7X3EqlSvcA0/M6/c/J9kJ3eupv
|
||||
jV8nAgMBAAGjggJ9MIICeTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYB
|
||||
BQUHAwEGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFAkdTjSCV3KD
|
||||
x28sf98MrwVfyFYgMB8GA1UdIwQYMBaAFMDMA0a5WCDMXHJw8+EuyyCm9Wg6MHcG
|
||||
CCsGAQUFBwEBBGswaTAyBggrBgEFBQcwAYYmaHR0cDovL29jc3Auc3RnLWludC14
|
||||
MS5sZXRzZW5jcnlwdC5vcmcwMwYIKwYBBQUHMAKGJ2h0dHA6Ly9jZXJ0LnN0Zy1p
|
||||
bnQteDEubGV0c2VuY3J5cHQub3JnLzArBgNVHREEJDAighAqLmRvY21pcnJvci5j
|
||||
bHVigg5kb2NtaXJyb3IuY2x1YjBMBgNVHSAERTBDMAgGBmeBDAECATA3BgsrBgEE
|
||||
AYLfEwEBATAoMCYGCCsGAQUFBwIBFhpodHRwOi8vY3BzLmxldHNlbmNyeXB0Lm9y
|
||||
ZzCCAQQGCisGAQQB1nkCBAIEgfUEgfIA8AB1ABboacHRlerXw/iXGuPwdgH3jOG2
|
||||
nTGoUhi2g38xqBUIAAABdmI3LM4AAAQDAEYwRAIgaiNqXSEq+sxp8eqlJXp/KFdO
|
||||
so5mT50MoRsLF8Inu0ACIDP46+ekng7I0BlmyIPmbqFcZgnZFVWLLCdLYijhVyOL
|
||||
AHcA3Zk0/KXnJIDJVmh9gTSZCEmySfe1adjHvKs/XMHzbmQAAAF2YjcuxwAABAMA
|
||||
SDBGAiEAxpeB8/w4YkHZ62nH20h128VtuTSmYDCnF7EK2fQyeZYCIQDbJlF2wehZ
|
||||
sF1BeE7qnYYqCTP0dYIrQ9HWtBa/MbGOKTANBgkqhkiG9w0BAQsFAAOCAQEAL2di
|
||||
HKh6XcZtGk0BFxJa51sCZ3MLu9+Zy90kCRD4ooP5x932WxVM25+LBRd+xSzx+TRL
|
||||
UVrlKp9GdMYX1JXL4Vf2NwzuFO3snPDe/qizD/3+D6yo8eKJ/LD82t5kLWAD2rto
|
||||
YfVSTKwfNIBBJwHUnjviBPJmheHHCKmz8Ct6/6QxFAeta9TAMn0sFeVCQnmAq7HL
|
||||
jrunq0tNHR/EKG0ITPLf+6P7MxbmpYNnq918766l0tKsW8oo8ZSGEwKU2LMaSiAa
|
||||
hasyl/2gMnYXjtKOjDcnR8oLpbrOg0qpVbynmJin1HP835oHPPAZ1gLsqYTTizNz
|
||||
AHxTaXliTVvS83dogw==
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEqzCCApOgAwIBAgIRAIvhKg5ZRO08VGQx8JdhT+UwDQYJKoZIhvcNAQELBQAw
|
||||
GjEYMBYGA1UEAwwPRmFrZSBMRSBSb290IFgxMB4XDTE2MDUyMzIyMDc1OVoXDTM2
|
||||
MDUyMzIyMDc1OVowIjEgMB4GA1UEAwwXRmFrZSBMRSBJbnRlcm1lZGlhdGUgWDEw
|
||||
ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDtWKySDn7rWZc5ggjz3ZB0
|
||||
8jO4xti3uzINfD5sQ7Lj7hzetUT+wQob+iXSZkhnvx+IvdbXF5/yt8aWPpUKnPym
|
||||
oLxsYiI5gQBLxNDzIec0OIaflWqAr29m7J8+NNtApEN8nZFnf3bhehZW7AxmS1m0
|
||||
ZnSsdHw0Fw+bgixPg2MQ9k9oefFeqa+7Kqdlz5bbrUYV2volxhDFtnI4Mh8BiWCN
|
||||
xDH1Hizq+GKCcHsinDZWurCqder/afJBnQs+SBSL6MVApHt+d35zjBD92fO2Je56
|
||||
dhMfzCgOKXeJ340WhW3TjD1zqLZXeaCyUNRnfOmWZV8nEhtHOFbUCU7r/KkjMZO9
|
||||
AgMBAAGjgeMwgeAwDgYDVR0PAQH/BAQDAgGGMBIGA1UdEwEB/wQIMAYBAf8CAQAw
|
||||
HQYDVR0OBBYEFMDMA0a5WCDMXHJw8+EuyyCm9Wg6MHoGCCsGAQUFBwEBBG4wbDA0
|
||||
BggrBgEFBQcwAYYoaHR0cDovL29jc3Auc3RnLXJvb3QteDEubGV0c2VuY3J5cHQu
|
||||
b3JnLzA0BggrBgEFBQcwAoYoaHR0cDovL2NlcnQuc3RnLXJvb3QteDEubGV0c2Vu
|
||||
Y3J5cHQub3JnLzAfBgNVHSMEGDAWgBTBJnSkikSg5vogKNhcI5pFiBh54DANBgkq
|
||||
hkiG9w0BAQsFAAOCAgEABYSu4Il+fI0MYU42OTmEj+1HqQ5DvyAeyCA6sGuZdwjF
|
||||
UGeVOv3NnLyfofuUOjEbY5irFCDtnv+0ckukUZN9lz4Q2YjWGUpW4TTu3ieTsaC9
|
||||
AFvCSgNHJyWSVtWvB5XDxsqawl1KzHzzwr132bF2rtGtazSqVqK9E07sGHMCf+zp
|
||||
DQVDVVGtqZPHwX3KqUtefE621b8RI6VCl4oD30Olf8pjuzG4JKBFRFclzLRjo/h7
|
||||
IkkfjZ8wDa7faOjVXx6n+eUQ29cIMCzr8/rNWHS9pYGGQKJiY2xmVC9h12H99Xyf
|
||||
zWE9vb5zKP3MVG6neX1hSdo7PEAb9fqRhHkqVsqUvJlIRmvXvVKTwNCP3eCjRCCI
|
||||
PTAvjV+4ni786iXwwFYNz8l3PmPLCyQXWGohnJ8iBm+5nk7O2ynaPVW0U2W+pt2w
|
||||
SVuvdDM5zGv2f9ltNWUiYZHJ1mmO97jSY/6YfdOUH66iRtQtDkHBRdkNBsMbD+Em
|
||||
2TgBldtHNSJBfB3pm9FblgOcJ0FSWcUDWJ7vO0+NTXlgrRofRT6pVywzxVo6dND0
|
||||
WzYlTWeUVsO40xJqhgUQRER9YLOLxJ0O6C8i0xFxAMKOtSdodMB3RIwt7RFQ0uyt
|
||||
n5Z5MqkYhlMI3J1tPRTp1nEt9fyGspBOO05gi148Qasp+3N+svqKomoQglNoAxU=
|
||||
-----END CERTIFICATE-----`
|
||||
describe('Certd', function () {
|
||||
it('#buildCertDir', function () {
|
||||
const options = createOptions()
|
||||
options.cert.email = 'xiaojunnuo@qq.com'
|
||||
options.cert.domains = ['*.docmirror.club']
|
||||
const certd = new Certd(options)
|
||||
const currentRootPath = certd.certStore.currentMarkPath
|
||||
console.log('rootDir', currentRootPath)
|
||||
expect(currentRootPath).match(/xiaojunnuo@qq.com\\certs\\_.docmirror.club-\w*\\current.json/)
|
||||
})
|
||||
it('#writeAndReadCert', async function () {
|
||||
const options = createOptions()
|
||||
options.cert.email = 'xiaojunnuo@qq.com'
|
||||
options.cert.domains = ['*.domain.cn']
|
||||
const certd = new Certd(options)
|
||||
await certd.writeCert({ csr: 'csr', crt: fakeCrt, key: 'bbb' })
|
||||
|
||||
const cert = await certd.readCurrentCert()
|
||||
expect(cert).to.be.ok
|
||||
expect(cert.crt).ok
|
||||
expect(cert.key).to.be.ok
|
||||
expect(cert.detail).to.be.ok
|
||||
expect(cert.expires).to.be.ok
|
||||
console.log('cert:', JSON.stringify(cert))
|
||||
})
|
||||
})
|
|
@ -1,14 +0,0 @@
|
|||
{
|
||||
"extends": "standard",
|
||||
"env": {
|
||||
"mocha": true
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.test.js", "*.spec.js"],
|
||||
"rules": {
|
||||
"no-unused-expressions": "off"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
.vscode/
|
||||
node_modules/
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
yarn.lock
|
||||
package-lock.json
|
||||
/.idea/
|
|
@ -1,39 +0,0 @@
|
|||
{
|
||||
"name": "@certd/executor",
|
||||
"version": "0.3.0",
|
||||
"description": "",
|
||||
"main": "src/index.js",
|
||||
"scripts": {
|
||||
"test": "echo \\\"Error: no test specified\\\" && exit 1",
|
||||
"build": "webpack --config webpack.config.cjs ",
|
||||
"rollup": "rollup --config rollup.config.js"
|
||||
},
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@certd/api": "^0.3.0",
|
||||
"@certd/certd": "^0.3.0",
|
||||
"dayjs": "^1.9.7",
|
||||
"lodash-es": "^4.17.20"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@certd/plugin-aliyun": "^0.3.0",
|
||||
"@certd/plugin-host": "^0.3.0",
|
||||
"@certd/plugin-tencent": "^0.3.0",
|
||||
"@rollup/plugin-commonjs": "^17.0.0",
|
||||
"@rollup/plugin-json": "^4.1.0",
|
||||
"@rollup/plugin-node-resolve": "^11.0.1",
|
||||
"chai": "^4.2.0",
|
||||
"eslint": "^7.15.0",
|
||||
"eslint-config-standard": "^16.0.2",
|
||||
"eslint-plugin-import": "^2.22.1",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-promise": "^4.2.1",
|
||||
"mocha": "^8.2.1",
|
||||
"rollup": "^2.35.1",
|
||||
"rollup-plugin-terser": "^7.0.2"
|
||||
},
|
||||
"author": "Greper",
|
||||
"license": "MIT",
|
||||
"sideEffects": false,
|
||||
"gitHead": "5fbd7742665c0a949333d805153e9b6af91c0a71"
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
import json from '@rollup/plugin-json'
|
||||
import { terser } from 'rollup-plugin-terser'
|
||||
import commonjs from '@rollup/plugin-commonjs'
|
||||
import { nodeResolve } from '@rollup/plugin-node-resolve'
|
||||
|
||||
export default {
|
||||
input: 'src/index.js',
|
||||
output: [
|
||||
{
|
||||
file: 'bundle.js',
|
||||
format: 'es'
|
||||
},
|
||||
{
|
||||
file: 'bundle.min.js',
|
||||
format: 'iife',
|
||||
name: 'version',
|
||||
plugins: [terser()]
|
||||
}
|
||||
],
|
||||
plugins: [json(), commonjs(), nodeResolve()]
|
||||
}
|
|
@ -1,182 +0,0 @@
|
|||
import { Certd } from '@certd/certd'
|
||||
import { pluginRegistry, util } from '@certd/api'
|
||||
import _ from 'lodash-es'
|
||||
import dayjs from 'dayjs'
|
||||
import { Trace } from './trace.js'
|
||||
const logger = util.logger
|
||||
|
||||
function createDefaultOptions () {
|
||||
return {
|
||||
args: {
|
||||
forceCert: false,
|
||||
forceDeploy: true,
|
||||
forceRedeploy: false,
|
||||
doNotThrowError: false // 部署流程执行有错误时,不抛异常,此时整个任务执行完毕后,可以返回结果,你可以在返回结果中处理
|
||||
}
|
||||
}
|
||||
}
|
||||
export class Executor {
|
||||
constructor () {
|
||||
this.trace = new Trace()
|
||||
}
|
||||
|
||||
async run (options) {
|
||||
logger.info('------------------- Cert-D ---------------------')
|
||||
try {
|
||||
this.transfer(options)
|
||||
options = _.merge(createDefaultOptions(), options)
|
||||
return await this.doRun(options)
|
||||
} catch (e) {
|
||||
logger.error('任务执行出错', e)
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
transfer (options) {
|
||||
const providers = options.accessProviders
|
||||
if (_.isArray(providers)) {
|
||||
const map = {}
|
||||
for (const provider of providers) {
|
||||
if (provider.key) {
|
||||
map[provider.key] = provider
|
||||
}
|
||||
}
|
||||
options.accessProviders = map
|
||||
}
|
||||
}
|
||||
|
||||
async doRun (options) {
|
||||
// 申请证书
|
||||
logger.info('任务开始')
|
||||
const certd = new Certd(options)
|
||||
const cert = await this.runCertd(certd)
|
||||
if (cert == null) {
|
||||
throw new Error('申请证书失败')
|
||||
}
|
||||
logger.info('证书保存路径:', cert.certDir)
|
||||
|
||||
logger.info('----------------------')
|
||||
if (!cert.isNew) {
|
||||
// 如果没有更新
|
||||
if (options.args.forceRedeploy) {
|
||||
// 强制重新部署,清空保存的状态
|
||||
await certd.certStore.setCurrentFile('context.json', '{}')
|
||||
} else if (!options.args.forceDeploy) {
|
||||
// 且不需要强制deploy
|
||||
logger.info('证书无更新,无需重新部署')
|
||||
logger.info('任务完成')
|
||||
return { cert }
|
||||
}
|
||||
}
|
||||
// 读取上次执行进度
|
||||
let context = {}
|
||||
const contextJson = await certd.certStore.getCurrentFile('context.json')
|
||||
if (contextJson) {
|
||||
context = JSON.parse(contextJson)
|
||||
}
|
||||
|
||||
context.certIsNew = !!cert.isNew
|
||||
|
||||
const trace = new Trace(context)
|
||||
const resultTrace = trace.getInstance({ type: 'result' })
|
||||
// 运行部署任务
|
||||
try {
|
||||
await this.runDeploys({ options, cert, context, trace })
|
||||
} finally {
|
||||
await certd.certStore.setCurrentFile('context.json', JSON.stringify(context))
|
||||
}
|
||||
logger.info('任务完成')
|
||||
trace.print()
|
||||
const result = resultTrace.get({ })
|
||||
if (result) {
|
||||
if (result.status === 'error' && options.args.doNotThrowError === false) {
|
||||
throw new Error(result.remark)
|
||||
}
|
||||
}
|
||||
return {
|
||||
cert,
|
||||
context,
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
async runCertd (certd) {
|
||||
logger.info(`证书任务 ${JSON.stringify(certd.options.cert.domains)} 开始`)
|
||||
const cert = await certd.certApply()
|
||||
logger.info(`证书任务 ${JSON.stringify(certd.options.cert.domains)} 完成`)
|
||||
return cert
|
||||
}
|
||||
|
||||
async runDeploys ({ options, cert, context, trace }) {
|
||||
if (cert == null) {
|
||||
const certd = new Certd(options)
|
||||
cert = await certd.readCurrentCert()
|
||||
}
|
||||
logger.info('部署任务开始')
|
||||
for (const deploy of options.deploy) {
|
||||
const deployName = deploy.deployName
|
||||
logger.info(`------------【${deployName}】-----------`)
|
||||
|
||||
const deployTrace = trace.getInstance({ type: 'deploy', deployName })
|
||||
if (deploy.disabled === true) {
|
||||
logger.info('此流程已被禁用,跳过')
|
||||
logger.info('')
|
||||
deployTrace.set({ value: { current: 'skip', status: 'disabled', remark: '流程禁用' } })
|
||||
deployTrace.set({ tasks: null })
|
||||
continue
|
||||
}
|
||||
try {
|
||||
for (const task of deploy.tasks) {
|
||||
if (context[deployName] == null) {
|
||||
context[deployName] = {}
|
||||
}
|
||||
const taskContext = context[deployName]
|
||||
// 开始执行任务列表
|
||||
await this.runTask({ options, cert, task, context: taskContext, deploy, trace })
|
||||
}
|
||||
|
||||
deployTrace.set({ value: { status: 'success', remark: '执行成功' } })
|
||||
trace.set({ type: 'result', value: { status: 'success', remark: '执行成功' } })
|
||||
} catch (e) {
|
||||
deployTrace.set({ value: { status: 'error', remark: '执行失败:' + e.message } })
|
||||
trace.set({ type: 'result', value: { status: 'error', remark: deployName + '执行失败:' + e.message } })
|
||||
logger.error('流程执行失败', e)
|
||||
}
|
||||
|
||||
logger.info('')
|
||||
}
|
||||
}
|
||||
|
||||
async runTask ({ options, task, cert, context, deploy, trace }) {
|
||||
const taskType = task.type
|
||||
const Plugin = pluginRegistry.get(taskType)
|
||||
const deployName = deploy.deployName
|
||||
const taskName = task.taskName
|
||||
if (Plugin == null) {
|
||||
throw new Error(`插件:${taskType}还未安装`)
|
||||
}
|
||||
|
||||
let instance = Plugin
|
||||
if (Plugin instanceof Function) {
|
||||
instance = new Plugin({ accessProviders: options.accessProviders })
|
||||
}
|
||||
const taskTrace = trace.getInstance({ type: 'deploy', deployName, taskName })
|
||||
const traceStatus = taskTrace.get({})
|
||||
if (traceStatus && traceStatus.status === 'success' && !options.args.forceRedeploy) {
|
||||
logger.info(`----【${taskName}】已经执行完成,跳过此任务`)
|
||||
taskTrace.set({ value: { current: 'skip', status: 'success', remark: '已执行成功过,本次跳过' } })
|
||||
return
|
||||
}
|
||||
logger.info(`----【${taskName}】开始执行`)
|
||||
try {
|
||||
// 执行任务
|
||||
await instance.execute({ cert, props: task.props, context })
|
||||
taskTrace.set({ value: { current: 'success', status: 'success', remark: '执行成功', time: dayjs().format() } })
|
||||
} catch (e) {
|
||||
taskTrace.set({ value: { current: 'error', status: 'error', remark: e.message, time: dayjs().format() } })
|
||||
throw e
|
||||
}
|
||||
logger.info(`----任务【${taskName}】执行完成`)
|
||||
logger.info('')
|
||||
}
|
||||
}
|
|
@ -1,96 +0,0 @@
|
|||
import { util } from '@certd/api'
|
||||
import _ from 'lodash-es'
|
||||
const logger = util.logger
|
||||
export class Trace {
|
||||
constructor (context) {
|
||||
this.context = context
|
||||
}
|
||||
|
||||
getInstance ({ type, deployName, taskName }) {
|
||||
return {
|
||||
get: ({ prop }) => {
|
||||
return this.get({ type, deployName, taskName, prop })
|
||||
},
|
||||
set: ({ prop, value }) => {
|
||||
this.set({ type, deployName, taskName, prop, value })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
set ({ type, deployName, taskName, prop, value }) {
|
||||
const key = this.buildTraceKey({ type, deployName, taskName, prop })
|
||||
const oldValue = _.get(this.context, key) || {}
|
||||
_.merge(oldValue, value)
|
||||
_.set(this.context, key, oldValue)
|
||||
}
|
||||
|
||||
get ({ type, deployName, taskName, prop }) {
|
||||
return _.get(this.context, this.buildTraceKey({ type, deployName, taskName, prop }))
|
||||
}
|
||||
|
||||
buildTraceKey ({ type = 'default', deployName, taskName, prop }) {
|
||||
let key = '__trace__.' + type
|
||||
if (deployName) {
|
||||
key += '.'
|
||||
key += deployName.replace(/\./g, '_')
|
||||
}
|
||||
if (taskName) {
|
||||
key += '.tasks.'
|
||||
key += taskName.replace(/\./g, '_')
|
||||
}
|
||||
if (prop) {
|
||||
key += '.' + prop
|
||||
}
|
||||
return key
|
||||
}
|
||||
|
||||
getStringLength (str) {
|
||||
const enLength = str.replace(/[\u0391-\uFFE5]/g, '').length // 先把中文替换成两个字节的英文,再计算长度
|
||||
return Math.floor((str.length - enLength) * 1.5) + enLength
|
||||
}
|
||||
|
||||
print () {
|
||||
const context = this.context
|
||||
logger.info('---------------------------任务结果总览--------------------------')
|
||||
if (context.certIsNew) {
|
||||
this.printTraceLine({ current: 'success', remark: '证书更新成功' }, '更新证书')
|
||||
} else {
|
||||
this.printTraceLine({ current: 'skip', remark: '还未到过期时间,跳过' }, '更新证书')
|
||||
}
|
||||
const trace = this.get({ type: 'deploy' })
|
||||
// logger.info('trace', trace)
|
||||
for (const deployName in trace) {
|
||||
if (trace[deployName] == null) {
|
||||
trace[deployName] = {}
|
||||
}
|
||||
const traceStatus = this.printTraceLine(trace[deployName], deployName)
|
||||
|
||||
const tasks = traceStatus.tasks
|
||||
if (tasks) {
|
||||
for (const taskName in tasks) {
|
||||
if (tasks[taskName] == null) {
|
||||
tasks[taskName] = {}
|
||||
}
|
||||
this.printTraceLine(tasks[taskName], taskName, ' └')
|
||||
}
|
||||
}
|
||||
}
|
||||
const result = this.get({ type: 'result' })
|
||||
if (result) {
|
||||
this.printTraceLine(result, 'result', '')
|
||||
}
|
||||
const mainContext = {}
|
||||
_.merge(mainContext, context)
|
||||
delete mainContext.__trace__
|
||||
logger.info('【context】', JSON.stringify(mainContext))
|
||||
}
|
||||
|
||||
printTraceLine (traceStatus, name, prefix = '') {
|
||||
const length = this.getStringLength(name)
|
||||
const endPad = _.repeat('-', 45 - prefix.length - length) + '\t'
|
||||
const status = traceStatus.current || traceStatus.status || ''
|
||||
const remark = traceStatus.remark || ''
|
||||
logger.info(`${prefix}【${name}】${endPad}[${status}] \t${remark}`)
|
||||
return traceStatus
|
||||
}
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
import pkg from 'chai'
|
||||
import { Executor } from '../src/index.js'
|
||||
import { createOptions } from '../../../../test/options.js'
|
||||
import PluginAliyun from '@certd/plugin-aliyun'
|
||||
import PluginTencent from '@certd/plugin-tencent'
|
||||
import PluginHost from '@certd/plugin-host'
|
||||
const { expect } = pkg
|
||||
|
||||
// 安装默认插件和授权提供者
|
||||
PluginAliyun.install()
|
||||
PluginTencent.install()
|
||||
PluginHost.install()
|
||||
|
||||
describe('AutoDeploy', function () {
|
||||
it('#run', async function () {
|
||||
this.timeout(120000)
|
||||
const options = createOptions()
|
||||
const executor = new Executor()
|
||||
const ret = await executor.run(options)
|
||||
expect(ret).ok
|
||||
expect(ret.cert).ok
|
||||
})
|
||||
it('#forceCert', async function () {
|
||||
this.timeout(120000)
|
||||
const executor = new Executor()
|
||||
const options = createOptions()
|
||||
options.args.forceCert = true
|
||||
options.args.forceDeploy = true
|
||||
|
||||
const ret = await executor.run(options)
|
||||
expect(ret).ok
|
||||
expect(ret.cert).ok
|
||||
})
|
||||
it('#forceDeploy', async function () {
|
||||
this.timeout(120000)
|
||||
const executor = new Executor()
|
||||
const options = createOptions()
|
||||
const ret = await executor.run(options, { forceCert: false, forceDeploy: true, forceRedeploy: true })
|
||||
expect(ret).ok
|
||||
expect(ret.cert).ok
|
||||
})
|
||||
})
|
|
@ -1,23 +0,0 @@
|
|||
const path = require('path')
|
||||
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
|
||||
console.log(CleanWebpackPlugin)
|
||||
|
||||
module.exports = {
|
||||
devtool: 'source-map',
|
||||
target: 'node',
|
||||
entry: './src/index.js',
|
||||
output: {
|
||||
filename: 'executor.js',
|
||||
path: path.resolve(__dirname, 'dist'),
|
||||
library: 'certdExecutor',
|
||||
libraryTarget: 'umd'
|
||||
},
|
||||
plugins: [
|
||||
new CleanWebpackPlugin()
|
||||
],
|
||||
mode: 'production'
|
||||
// mode: 'development',
|
||||
// optimization: {
|
||||
// usedExports: true
|
||||
// }
|
||||
}
|
|
@ -18,7 +18,6 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@types/lodash": "^4.14.186",
|
||||
"@fast-crud/fast-crud": "^1.5.0",
|
||||
"vue-tsc": "^0.38.9",
|
||||
"@alicloud/cs20151215": "^3.0.3",
|
||||
"@alicloud/openapi-client": "^0.4.0",
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
import { Registrable } from "../registry";
|
||||
import { FormItemProps } from "@fast-crud/fast-crud";
|
||||
import { accessRegistry } from "./registry";
|
||||
import { FormItemProps } from "../d.ts";
|
||||
|
||||
export type AccessInput = FormItemProps & {
|
||||
title: string;
|
||||
required?: boolean;
|
||||
};
|
||||
export type AccessDefine = Registrable & {
|
||||
input: {
|
||||
[key: string]: FormItemProps;
|
||||
[key: string]: AccessInput;
|
||||
};
|
||||
};
|
||||
export function IsAccess(define: AccessDefine) {
|
||||
|
|
|
@ -7,11 +7,18 @@ import { AbstractAccess } from "../abstract-access";
|
|||
desc: "",
|
||||
input: {
|
||||
accessKeyId: {
|
||||
title: "accessKeyId",
|
||||
component: {
|
||||
placeholder: "accessKeyId",
|
||||
},
|
||||
//required: true,
|
||||
//rules: [{ required: true, message: "必填项" }],
|
||||
required: true,
|
||||
},
|
||||
accessKeySecret: {
|
||||
title: "accessKeySecret",
|
||||
component: {
|
||||
placeholder: "accessKeySecret",
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
/**
|
||||
* [x]-col的配置
|
||||
*/
|
||||
export type ColProps = {
|
||||
span?: number;
|
||||
[props: string]: any;
|
||||
};
|
||||
|
||||
export type FormItemProps = {
|
||||
/**
|
||||
* 字段label
|
||||
*/
|
||||
title?: string;
|
||||
/**
|
||||
* 表单字段组件配置
|
||||
*/
|
||||
component?: ComponentProps;
|
||||
/**
|
||||
* 表单字段 [a|el|n]-col的配置
|
||||
* 一般用来配置跨列:{span:24} 占满一行
|
||||
*/
|
||||
col?: ColProps;
|
||||
/**
|
||||
* 默认值
|
||||
*/
|
||||
value?: any;
|
||||
/**
|
||||
* 帮助提示配置
|
||||
*/
|
||||
helper?: string | FormItemHelperProps;
|
||||
/**
|
||||
* 排序号
|
||||
*/
|
||||
order?: number;
|
||||
/**
|
||||
* 是否显示此字段
|
||||
*/
|
||||
show?: boolean;
|
||||
/**
|
||||
* 是否是空白占位栏
|
||||
*/
|
||||
blank?: boolean;
|
||||
|
||||
[key: string]: any;
|
||||
};
|
||||
|
||||
/**
|
||||
* 表单字段帮助说明配置
|
||||
*/
|
||||
export type FormItemHelperProps = {
|
||||
/**
|
||||
* 自定义渲染帮助说明
|
||||
* @param scope
|
||||
*/
|
||||
render?: (scope: any) => any;
|
||||
/**
|
||||
* 帮助文本
|
||||
*/
|
||||
text?: string;
|
||||
/**
|
||||
* 帮助说明所在的位置,[ undefined | label]
|
||||
*/
|
||||
position?: string;
|
||||
/**
|
||||
* [a|el|n]-tooltip配置
|
||||
*/
|
||||
tooltip?: object;
|
||||
|
||||
[key: string]: any;
|
||||
};
|
||||
|
||||
/**
|
||||
* 组件配置
|
||||
*/
|
||||
export type ComponentProps = {
|
||||
/**
|
||||
* 组件的名称
|
||||
*/
|
||||
name?: string | object;
|
||||
/**
|
||||
* vmodel绑定的目标属性名
|
||||
*/
|
||||
vModel?: string;
|
||||
|
||||
/**
|
||||
* 当原始组件名的参数被以上属性名占用时,可以配置在这里
|
||||
* 例如:原始组件有一个叫name的属性,你想要配置它,则可以按如下配置
|
||||
* ```
|
||||
* component:{
|
||||
* name:"组件的名称"
|
||||
* props:{
|
||||
* name:"组件的name属性" <-----------
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
props?: {
|
||||
[key: string]: any;
|
||||
};
|
||||
|
||||
/**
|
||||
* 组件事件监听
|
||||
*/
|
||||
on?: {
|
||||
[key: string]: (context?: any) => void;
|
||||
};
|
||||
|
||||
/**
|
||||
* 组件其他参数
|
||||
* 事件:onXxx:(event)=>void 组件原始事件监听
|
||||
* on.onXxx:(context)=>void 组件事件监听(对原始事件包装)
|
||||
* 样式:style、class等
|
||||
*/
|
||||
[key: string]: any;
|
||||
};
|
|
@ -1 +1,2 @@
|
|||
export * from "./pipeline";
|
||||
export * from "./fast-crud";
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { FormItemProps } from "@fast-crud/fast-crud";
|
||||
import { Registrable } from "../registry";
|
||||
import { pluginRegistry } from "./registry";
|
||||
import { FormItemProps } from "../d.ts";
|
||||
export type TaskInput = {
|
||||
[key: string]: any;
|
||||
};
|
||||
|
|
|
@ -5,7 +5,7 @@ import dayjs from "dayjs";
|
|||
import { dnsProviderRegistry } from "../../../dns-provider";
|
||||
import { AbstractDnsProvider } from "../../../dns-provider/abstract-dns-provider";
|
||||
import { AcmeService } from "./acme";
|
||||
|
||||
import _ from "lodash";
|
||||
export type CertInfo = {
|
||||
crt: string;
|
||||
key: string;
|
||||
|
@ -15,6 +15,7 @@ export type CertInfo = {
|
|||
return {
|
||||
name: "CertApply",
|
||||
title: "证书申请",
|
||||
desc: "免费通配符域名证书申请,支持多个域名打到同一个证书上",
|
||||
input: {
|
||||
domains: {
|
||||
title: "域名",
|
||||
|
@ -22,12 +23,17 @@ export type CertInfo = {
|
|||
name: "a-select",
|
||||
vModel: "value",
|
||||
mode: "tags",
|
||||
open: false,
|
||||
},
|
||||
required: true,
|
||||
col: {
|
||||
span: 24,
|
||||
},
|
||||
helper: "请输入域名",
|
||||
helper:
|
||||
"支持通配符域名,例如: *.foo.com 、 *.test.handsfree.work\n" +
|
||||
"支持多个域名、多个子域名、多个通配符域名打到一个证书上(域名必须是在同一个DNS提供商解析)\n" +
|
||||
"多级子域名要分成多个域名输入(*.foo.com的证书不能用于xxx.yyy.foo.com)\n" +
|
||||
"输入一个回车之后,再输入下一个",
|
||||
},
|
||||
email: {
|
||||
title: "邮箱",
|
||||
|
@ -138,7 +144,17 @@ export class CertApplyPlugin extends AbstractPlugin implements TaskPlugin {
|
|||
const domains = input["domains"];
|
||||
const dnsProviderType = input["dnsProviderType"];
|
||||
const dnsProviderAccessId = input["dnsProviderAccess"];
|
||||
const csrInfo = input["csrInfo"];
|
||||
const csrInfo = _.merge(
|
||||
{
|
||||
country: "CN",
|
||||
state: "GuangDong",
|
||||
locality: "ShengZhen",
|
||||
organization: "CertD Org.",
|
||||
organizationUnit: "IT Department",
|
||||
emailAddress: email,
|
||||
},
|
||||
input["csrInfo"]
|
||||
);
|
||||
this.logger.info("开始申请证书,", email, domains);
|
||||
|
||||
const dnsProviderClass = dnsProviderRegistry.get(dnsProviderType);
|
||||
|
|
|
@ -59,11 +59,21 @@ export class Registry<T extends typeof AbstractRegistrable> {
|
|||
getDefineList() {
|
||||
const list = [];
|
||||
for (const key in this.storage) {
|
||||
const PluginClass = this.storage[key];
|
||||
// @ts-ignore
|
||||
const plugin = new PluginClass();
|
||||
list.push({ ...plugin.define, key });
|
||||
const define = this.getDefine(key);
|
||||
if (define) {
|
||||
list.push({ ...define, key });
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
getDefine(key: string) {
|
||||
const PluginClass = this.storage[key];
|
||||
if (!PluginClass) {
|
||||
return;
|
||||
}
|
||||
// @ts-ignore
|
||||
const plugin = new PluginClass();
|
||||
return plugin.define;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ export const pipeline: Pipeline = {
|
|||
version: 1,
|
||||
id: generateId(),
|
||||
title: "测试管道",
|
||||
userId: 1,
|
||||
triggers: [],
|
||||
stages: [
|
||||
{
|
||||
|
|
|
@ -7,5 +7,18 @@ export default defineConfig({
|
|||
entry: "src/index.ts",
|
||||
name: "pipeline",
|
||||
},
|
||||
rollupOptions: {
|
||||
external: ["vue", "lodash-es", "dayjs", "@fast-crud/fast-crud"],
|
||||
output: {
|
||||
// Provide global variables to use in the UMD build
|
||||
// for externalized deps
|
||||
globals: {
|
||||
vue: "Vue",
|
||||
"lodash-es": "_",
|
||||
dayjs: "dayjs",
|
||||
"@fast-crud/fast-crud": "FastCrud",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit f7d9e45c8abb051e8cd8388618e694f8757cb15e
|
||||
Subproject commit 70f49940d71f5c74087ecd9038881291f250f7d6
|
|
@ -1 +1 @@
|
|||
Subproject commit 60695c23553c28a4bb710f55e1a56e623d7fafd3
|
||||
Subproject commit a0366be6aeda29aa55d3c5b9f775fa3a27a322a3
|
|
@ -1,16 +0,0 @@
|
|||
module.exports = {
|
||||
root: true,
|
||||
parserOptions: {
|
||||
sourceType: 'module',
|
||||
ecmaVersion: '2020'
|
||||
},
|
||||
parser: 'babel-eslint',
|
||||
extends: ['standard'],
|
||||
env: {
|
||||
node: true
|
||||
},
|
||||
rules: {
|
||||
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
|
||||
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off'
|
||||
}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
.vscode/
|
||||
node_modules/
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
yarn.lock
|
||||
package-lock.json
|
||||
/.idea/
|
|
@ -1,6 +0,0 @@
|
|||
FROM registry.cn-shenzhen.aliyuncs.com/greper/node:15.8.0-alpine
|
||||
ENV TZ=Asia/Shanghai
|
||||
EXPOSE 3000
|
||||
ADD ./ /app/
|
||||
RUN cd /app/ && ls
|
||||
ENTRYPOINT node /app/bin/www.js
|
|
@ -1,59 +0,0 @@
|
|||
import Koa from 'koa'
|
||||
import json from 'koa-json'
|
||||
import onerror from 'koa-onerror'
|
||||
import bodyparser from 'koa-bodyparser'
|
||||
import logger from 'koa-logger'
|
||||
import Static from 'koa-static'
|
||||
import fs from 'fs'
|
||||
import _ from 'lodash-es'
|
||||
import './install.js'
|
||||
import pathUtil from './utils/util.path.js'
|
||||
import compress from 'koa-compress'
|
||||
const app = new Koa()
|
||||
|
||||
// error handler
|
||||
onerror(app)
|
||||
|
||||
// middlewares
|
||||
app.use(bodyparser({
|
||||
enableTypes: ['json', 'form', 'text']
|
||||
}))
|
||||
app.use(json())
|
||||
app.use(logger())
|
||||
// gzip
|
||||
// app.use(compress({ threshold: 5120 }))
|
||||
|
||||
const staticPlugin = Static(pathUtil.join('public'), {
|
||||
maxage: 30 * 24 * 60 * 3600,
|
||||
gzip: true
|
||||
})
|
||||
app.use(staticPlugin)
|
||||
|
||||
// logger
|
||||
app.use(async (ctx, next) => {
|
||||
const start = new Date()
|
||||
await next()
|
||||
const ms = new Date() - start
|
||||
console.log(`${ctx.method} ${ctx.url} - ${ms}ms`)
|
||||
})
|
||||
|
||||
// routes
|
||||
const files = fs.readdirSync(new URL('controllers/', import.meta.url))
|
||||
// 过滤出.js文件:
|
||||
const jsFiles = files.filter((f) => {
|
||||
return f.endsWith('.js')
|
||||
})
|
||||
|
||||
_.forEach(jsFiles, async item => {
|
||||
let mapping = await import(new URL('controllers/' + item, import.meta.url))
|
||||
mapping = mapping.default
|
||||
app.use(mapping.routes(), mapping.allowedMethods())
|
||||
})
|
||||
|
||||
// error-handling
|
||||
app.on('error', (err, ctx) => {
|
||||
console.error('server error', err, ctx)
|
||||
})
|
||||
|
||||
console.log('http://localhost:3000/')
|
||||
export default app
|
|
@ -1,93 +0,0 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
import app from '../app.js';
|
||||
import debuger from 'debug'
|
||||
const debug = debuger('demo:serer')
|
||||
// require('debug')('demo:server');
|
||||
import http from 'http';
|
||||
|
||||
/**
|
||||
* Get port from environment and store in Express.
|
||||
*/
|
||||
|
||||
var port = normalizePort(process.env.PORT || '3000');
|
||||
// app.set('port', port);
|
||||
|
||||
/**
|
||||
* Create HTTP server.
|
||||
*/
|
||||
|
||||
var server = http.createServer(app.callback());
|
||||
|
||||
/**
|
||||
* Listen on provided port, on all network interfaces.
|
||||
*/
|
||||
|
||||
server.listen(port);
|
||||
server.on('error', onError);
|
||||
server.on('listening', onListening);
|
||||
|
||||
/**
|
||||
* Normalize a port into a number, string, or false.
|
||||
*/
|
||||
|
||||
function normalizePort(val) {
|
||||
var port = parseInt(val, 10);
|
||||
|
||||
if (isNaN(port)) {
|
||||
// named pipe
|
||||
return val;
|
||||
}
|
||||
|
||||
if (port >= 0) {
|
||||
// port number
|
||||
return port;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Event listener for HTTP server "error" event.
|
||||
*/
|
||||
|
||||
function onError(error) {
|
||||
if (error.syscall !== 'listen') {
|
||||
throw error;
|
||||
}
|
||||
|
||||
var bind = typeof port === 'string'
|
||||
? 'Pipe ' + port
|
||||
: 'Port ' + port;
|
||||
|
||||
// handle specific listen errors with friendly messages
|
||||
switch (error.code) {
|
||||
case 'EACCES':
|
||||
console.error(bind + ' requires elevated privileges');
|
||||
process.exit(1);
|
||||
break;
|
||||
case 'EADDRINUSE':
|
||||
console.error(bind + ' is already in use');
|
||||
process.exit(1);
|
||||
break;
|
||||
default:
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Event listener for HTTP server "listening" event.
|
||||
*/
|
||||
|
||||
function onListening() {
|
||||
var addr = server.address();
|
||||
var bind = typeof addr === 'string'
|
||||
? 'pipe ' + addr
|
||||
: 'port ' + addr.port;
|
||||
debug('Listening on ' + bind);
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
import Router from 'koa-router'
|
||||
import { accessProviderRegistry } from '@certd/api'
|
||||
import _ from 'lodash-es'
|
||||
import { Ret } from '../models/Ret.js'
|
||||
const router = Router()
|
||||
router.prefix('/api/access-providers')
|
||||
|
||||
router.get('/list', function (ctx, next) {
|
||||
const list = []
|
||||
_.forEach(accessProviderRegistry.collection, item => {
|
||||
list.push(item.define())
|
||||
})
|
||||
ctx.body = Ret.success(list)
|
||||
})
|
||||
|
||||
export default router
|
|
@ -1,16 +0,0 @@
|
|||
import Router from 'koa-router'
|
||||
import { dnsProviderRegistry } from '@certd/api'
|
||||
import _ from 'lodash-es'
|
||||
import { Ret } from '../models/Ret.js'
|
||||
const router = Router()
|
||||
router.prefix('/api/dns-providers')
|
||||
|
||||
router.get('/list', function (ctx, next) {
|
||||
const list = []
|
||||
_.forEach(dnsProviderRegistry.collection, item => {
|
||||
list.push(item.define())
|
||||
})
|
||||
ctx.body = Ret.success(list)
|
||||
})
|
||||
|
||||
export default router
|
|
@ -1,23 +0,0 @@
|
|||
import Router from 'koa-router'
|
||||
import fs from 'fs'
|
||||
import exportsService from '../service/exports-service.js'
|
||||
|
||||
const router = Router()
|
||||
router.prefix('/api/exports')
|
||||
|
||||
router.post('/toZip', async function (ctx, next) {
|
||||
// const request = ctx.request
|
||||
// const query = request.query
|
||||
const body = ctx.request.body
|
||||
// const req_queryString = request.queryString
|
||||
const { zipPath, fileName } = await exportsService.exportsToZip(body.options, 'certd-run')
|
||||
|
||||
console.log('zipFile', zipPath)
|
||||
ctx.set('Content-disposition', 'attachment;filename=' + fileName)
|
||||
ctx.set('Content-Type', 'application/zip')
|
||||
ctx.body = fs.createReadStream(zipPath)
|
||||
//
|
||||
// // ctx.body = Ret.success(zipPath)
|
||||
})
|
||||
|
||||
export default router
|
|
@ -1,10 +0,0 @@
|
|||
import Router from 'koa-router'
|
||||
const router = Router()
|
||||
|
||||
router.get('/api/', async (ctx, next) => {
|
||||
await ctx.render('index', {
|
||||
title: 'Hello CertD!'
|
||||
})
|
||||
})
|
||||
|
||||
export default router
|
|
@ -1,16 +0,0 @@
|
|||
import Router from 'koa-router'
|
||||
import { pluginRegistry } from '@certd/api'
|
||||
import _ from 'lodash-es'
|
||||
import { Ret } from '../models/Ret.js'
|
||||
const router = Router()
|
||||
router.prefix('/api/plugins')
|
||||
|
||||
router.get('/list', function (ctx, next) {
|
||||
const list = []
|
||||
_.forEach(pluginRegistry.collection, item => {
|
||||
list.push(item.define())
|
||||
})
|
||||
ctx.body = Ret.success(list)
|
||||
})
|
||||
|
||||
export default router
|
|
@ -1,8 +0,0 @@
|
|||
import PluginAliyun from '@certd/plugin-aliyun'
|
||||
import PluginTencent from '@certd/plugin-tencent'
|
||||
import PluginHost from '@certd/plugin-host'
|
||||
|
||||
// 安装默认插件和授权提供者
|
||||
PluginAliyun.install()
|
||||
PluginTencent.install()
|
||||
PluginHost.install()
|
|
@ -1,15 +0,0 @@
|
|||
export class Ret {
|
||||
constructor (code = 0, msg, data) {
|
||||
this.code = code
|
||||
this.msg = msg
|
||||
this.data = data
|
||||
}
|
||||
|
||||
static success (data) {
|
||||
return new Ret(0, '', data)
|
||||
}
|
||||
|
||||
static error (msg) {
|
||||
return new Ret(1, msg)
|
||||
}
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
{
|
||||
"name": "@certd/server",
|
||||
"version": "0.2.2",
|
||||
"private": false,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"start": "node bin/www.js",
|
||||
"dev": "./node_modules/.bin/nodemon bin/www.js",
|
||||
"prd": "pm2 start bin/www.js",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@certd/api": "^0.3.0",
|
||||
"@certd/executor": "^0.3.0",
|
||||
"@certd/plugin-aliyun": "^0.3.0",
|
||||
"@certd/plugin-host": "^0.3.0",
|
||||
"@certd/plugin-tencent": "^0.3.0",
|
||||
"compressing": "^1.5.1",
|
||||
"debug": "^4.1.1",
|
||||
"fs-extra": "^9.1.0",
|
||||
"koa": "^2.7.0",
|
||||
"koa-bodyparser": "^4.2.1",
|
||||
"koa-compress": "^5.0.1",
|
||||
"koa-convert": "^1.2.0",
|
||||
"koa-json": "^2.0.2",
|
||||
"koa-logger": "^3.2.0",
|
||||
"koa-onerror": "^4.1.0",
|
||||
"koa-router": "^7.4.0",
|
||||
"koa-static": "^5.0.0",
|
||||
"koa-views": "^6.2.0",
|
||||
"lodash-es": "^4.17.20"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-eslint": "^10.1.0",
|
||||
"eslint": "^7.19.0",
|
||||
"eslint-config-standard": "^16.0.2",
|
||||
"eslint-plugin-import": "^2.22.1",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-promise": "^4.2.1",
|
||||
"nodemon": "^1.19.1"
|
||||
},
|
||||
"gitHead": "5fbd7742665c0a949333d805153e9b6af91c0a71"
|
||||
}
|
Before Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 7.4 KiB |
|
@ -1,17 +0,0 @@
|
|||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||
width="500" height="500" viewBox="0 0 500.000000 500.000000"
|
||||
>
|
||||
|
||||
|
||||
|
||||
<path d="M28.34 56.68h28.34V36.12H28.34a7.79 7.79 0 1 1 0-15.58h19.84v9.05h8.5V12H28.34a16.29 16.29 0 0 0 0 32.58h19.84v3.56H28.34a19.84 19.84 0 0 1 0-39.68h28.34V0H28.34a28.34 28.34 0 0 0 0 56.68z"
|
||||
fill="#2c3e50"
|
||||
transform="translate(124, 60) scale(4,4)"
|
||||
></path>
|
||||
<path d="M13.00-21.91L21.24-21.91L21.24-17.23L14.04-17.23Q10.39-17.23 9-15.62L9-15.62Q7.65-14.08 7.65-10.93L7.65-10.93Q7.65-7.42 9.86-5.80L9.86-5.80Q10.75-5.17 11.81-4.93Q12.87-4.68 14.76-4.68L14.76-4.68L21.24-4.68L21.24 0L13.00 0Q9.67 0 7.74-0.67Q5.80-1.35 4.32-3.01L4.32-3.01Q1.48-6.17 1.48-11.03L1.48-11.03Q1.48-16.88 4.86-19.75L4.86-19.75Q6.21-20.93 8.10-21.42Q9.99-21.91 13.00-21.91L13.00-21.91ZM31.05-13.32L43.74-13.32L43.74-8.64L31.05-8.64Q31.23-6.48 32.44-5.58Q33.66-4.68 36.41-4.68L36.41-4.68L43.74-4.68L43.74 0L35.73 0Q33.12 0 31.48-0.47Q29.83-0.94 28.39-2.02L28.39-2.02Q24.39-5.13 24.39-11.25L24.39-11.25Q24.39-15.21 26.50-18.18L26.50-18.18Q27.94-20.20 29.97-21.06Q31.99-21.91 35.28-21.91L35.28-21.91L43.74-21.91L43.74-17.23L35.73-17.23Q33.25-17.23 32.27-16.40Q31.27-15.57 31.05-13.32L31.05-13.32ZM48.64 0L48.64-21.91L57.55-21.91Q60.30-21.91 61.81-21.53Q63.31-21.15 64.31-20.25L64.31-20.25Q65.30-19.35 65.70-18Q66.10-16.65 66.10-14.13L66.10-14.13L66.10-12.01L60.30-12.01L60.30-13.18Q60.30-15.52 59.49-16.38Q58.68-17.23 56.38-17.23L56.38-17.23L54.67-17.23L54.67 0L48.64 0ZM67.50-21.91L71.33-21.91L71.33-30.02L77.36-30.02L77.36-21.91L82.94-21.91L82.94-17.23L77.36-17.23L77.36-9.27Q77.36-6.48 77.85-5.76L77.85-5.76Q78.61-4.68 80.55-4.68L80.55-4.68L82.94-4.68L82.94 0L78.57 0Q74.66 0 72.99-1.89Q71.33-3.78 71.33-8.23L71.33-8.23L71.33-17.23L67.50-17.23L67.50-21.91ZM96.08-21.91L101.75-21.91L101.75-30.02L107.73-30.02L107.73 0L97.38 0Q94.23 0 92.61-0.49L92.61-0.49Q88.78-1.71 86.90-5.26L86.90-5.26Q85.59-7.65 85.59-11.12L85.59-11.12Q85.59-16.74 89.37-19.84L89.37-19.84Q91.84-21.91 96.08-21.91L96.08-21.91ZM97.38-4.68L101.75-4.68L101.75-17.23L97.38-17.23Q94.50-17.23 93.02-15.30L93.02-15.30Q91.71-13.68 91.71-11.12L91.71-11.12Q91.71-7.38 93.87-5.76L93.87-5.76Q95.36-4.68 97.38-4.68L97.38-4.68Z"
|
||||
fill="#2c3e50"
|
||||
transform="translate(28, 430) scale(4,4)"
|
||||
|
||||
></path>
|
||||
|
||||
</svg>
|
Before Width: | Height: | Size: 2.3 KiB |
|
@ -1,55 +0,0 @@
|
|||
import os from 'os'
|
||||
import fs from 'fs-extra'
|
||||
import pathUtil from '../utils/util.path.js'
|
||||
import cryptoRandomString from 'crypto-random-string'
|
||||
import zipUtil from '../utils/util.zip.js'
|
||||
import path from 'path'
|
||||
|
||||
import { createRequire } from 'module'
|
||||
const require = createRequire(import.meta.url)
|
||||
|
||||
export default {
|
||||
async exportsToZip (options, dirName) {
|
||||
const tempDir = os.tmpdir()
|
||||
const targetDir = path.join(tempDir, 'certd-server', cryptoRandomString(10))
|
||||
const projectName = dirName
|
||||
const targetProjectDir = path.join(targetDir, projectName)
|
||||
const templateDir = pathUtil.join('templates/' + projectName)
|
||||
|
||||
console.log('targetDir', targetDir)
|
||||
console.log('projectName', projectName)
|
||||
console.log('tempalteDir', templateDir)
|
||||
console.log('targetProjectDir', targetProjectDir)
|
||||
fs.copySync(templateDir, targetProjectDir)
|
||||
|
||||
// options
|
||||
const optionsFilePath = path.join(targetProjectDir, 'options.json')
|
||||
fs.writeJsonSync(optionsFilePath, options)
|
||||
|
||||
// 依赖版本
|
||||
const exePkgJson = fs.readFileSync(pathUtil.join('node_modules/@certd/executor/package.json'))
|
||||
const executorPkg = JSON.parse(exePkgJson)
|
||||
const currentVersion = executorPkg.version
|
||||
|
||||
const templatePkgJson = fs.readFileSync(pathUtil.join('templates/certd-run/package.json'))
|
||||
const templatePkg = JSON.parse(templatePkgJson)
|
||||
templatePkg.dependencies['@certd/executor'] = '^' + currentVersion
|
||||
templatePkg.dependencies['@certd/plugin-aliyun'] = '^' + currentVersion
|
||||
templatePkg.dependencies['@certd/plugin-host'] = '^' + currentVersion
|
||||
templatePkg.dependencies['@certd/plugin-tencent'] = '^' + currentVersion
|
||||
const pkgFilePath = path.join(targetProjectDir, 'package.json')
|
||||
fs.writeJsonSync(pkgFilePath, templatePkg)
|
||||
|
||||
const zipName = dirName + '.zip'
|
||||
const outputFilePath = path.join(targetDir, zipName)
|
||||
|
||||
console.log('outputFilePath', outputFilePath)
|
||||
await zipUtil.compress({ dir: targetProjectDir, output: outputFilePath })
|
||||
return {
|
||||
dir: targetDir,
|
||||
fileName: zipName,
|
||||
zipPath: outputFilePath
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
import { Executor } from '@certd/executor'
|
||||
import PluginAliyun from '@certd/plugin-aliyun'
|
||||
import PluginTencent from '@certd/plugin-tencent'
|
||||
import PluginHost from '@certd/plugin-host'
|
||||
|
||||
// import options
|
||||
import { createRequire } from 'module'
|
||||
|
||||
// 安装默认插件和授权提供者
|
||||
PluginAliyun.install()
|
||||
PluginTencent.install()
|
||||
PluginHost.install()
|
||||
const require = createRequire(import.meta.url)
|
||||
const options = require('./options.json')
|
||||
|
||||
// 开始执行
|
||||
const executor = new Executor()
|
||||
await executor.run(options)
|
|
@ -1 +0,0 @@
|
|||
{}
|
|
@ -1,22 +0,0 @@
|
|||
{
|
||||
"name": "certd-run",
|
||||
"version": "1.0.0",
|
||||
"description": "certd run",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"certd": "node index.js"
|
||||
},
|
||||
"type": "module",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/certd/certd"
|
||||
},
|
||||
"author": "greper",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@certd/executor": "^0.3.0",
|
||||
"@certd/plugin-aliyun": "^0.3.0",
|
||||
"@certd/plugin-host": "^0.3.0",
|
||||
"@certd/plugin-tencent": "^0.3.0"
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
import os from 'os'
|
||||
export default {
|
||||
join (...dirs) {
|
||||
const url = new URL('../' + dirs.join('/'), import.meta.url)
|
||||
let path = url.pathname
|
||||
if (os.type() === 'Windows_NT') {
|
||||
path = path.substring(1)
|
||||
}
|
||||
return path
|
||||
}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
import compressing from 'compressing'
|
||||
export default {
|
||||
compress ({
|
||||
dir, output
|
||||
}) {
|
||||
return compressing.zip.compressDir(dir, output)
|
||||
}
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
> 1%
|
||||
last 2 versions
|
||||
not dead
|
|
@ -1,5 +0,0 @@
|
|||
[*.{js,jsx,ts,tsx,vue}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
|
@ -1 +0,0 @@
|
|||
VITE_APP_API=/api
|
|
@ -1,2 +0,0 @@
|
|||
node_modules
|
||||
.idea
|
|
@ -1,76 +0,0 @@
|
|||
module.exports = {
|
||||
root: true,
|
||||
env: {
|
||||
browser: true,
|
||||
node: true,
|
||||
es6: true
|
||||
},
|
||||
parser: "vue-eslint-parser",
|
||||
parserOptions: {
|
||||
parser: "@typescript-eslint/parser",
|
||||
ecmaVersion: 2020,
|
||||
sourceType: "module",
|
||||
jsxPragma: "React",
|
||||
ecmaFeatures: {
|
||||
jsx: true,
|
||||
tsx: true
|
||||
}
|
||||
},
|
||||
extends: [
|
||||
"plugin:vue/vue3-recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:prettier/recommended",
|
||||
"prettier"
|
||||
],
|
||||
rules: {
|
||||
//"max-len": [0, 200, 2, { ignoreUrls: true }],
|
||||
"@typescript-eslint/ban-ts-ignore": "off",
|
||||
"@typescript-eslint/explicit-function-return-type": "off",
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"@typescript-eslint/no-var-requires": "off",
|
||||
"@typescript-eslint/no-empty-function": "off",
|
||||
"@typescript-eslint/no-use-before-define": "off",
|
||||
"@typescript-eslint/ban-ts-comment": "off",
|
||||
"@typescript-eslint/ban-types": "off",
|
||||
"@typescript-eslint/no-non-null-assertion": "off",
|
||||
"@typescript-eslint/explicit-module-boundary-types": "off"
|
||||
// "@typescript-eslint/no-unused-vars": [
|
||||
// "error",
|
||||
// {
|
||||
// argsIgnorePattern: "^h$",
|
||||
// varsIgnorePattern: "^h$",
|
||||
// },
|
||||
// ],
|
||||
// "no-unused-vars": [
|
||||
// "error",
|
||||
// {
|
||||
// argsIgnorePattern: "^h$",
|
||||
// varsIgnorePattern: "^h$",
|
||||
// },
|
||||
// ],
|
||||
// "vue/custom-event-name-casing": "off",
|
||||
// "no-use-before-define": "off",
|
||||
// "space-before-function-paren": "off",
|
||||
|
||||
// "vue/attributes-order": "off",
|
||||
// "vue/one-component-per-file": "off",
|
||||
// "vue/html-closing-bracket-newline": "off",
|
||||
// "vue/max-attributes-per-line": "off",
|
||||
// "vue/multiline-html-element-content-newline": "off",
|
||||
// "vue/singleline-html-element-content-newline": "off",
|
||||
// "vue/attribute-hyphenation": "off",
|
||||
// "vue/require-default-prop": "off",
|
||||
// "vue/html-self-closing": [
|
||||
// "error",
|
||||
// {
|
||||
// html: {
|
||||
// void: "always",
|
||||
// normal: "never",
|
||||
// component: "always",
|
||||
// },
|
||||
// svg: "always",
|
||||
// math: "always",
|
||||
// },
|
||||
// ],
|
||||
}
|
||||
};
|
|
@ -1,11 +0,0 @@
|
|||
node_modules
|
||||
.DS_Store
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
/stats.html
|
||||
yarn.lock
|
||||
.idea
|
||||
/.idea/
|
||||
yarn-error.log
|
||||
vite-profile.cpuprofile
|
|
@ -1,2 +0,0 @@
|
|||
node_modules
|
||||
/stats.html
|
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
|
||||
"trailingComma": "none",
|
||||
"printWidth": 120
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
# certd-ui
|
||||
|
||||
## Project setup
|
||||
```
|
||||
npm install
|
||||
```
|
||||
|
||||
### Compiles and hot-reloads for development
|
||||
```
|
||||
npm run serve
|
||||
```
|
||||
|
||||
### Compiles and minifies for production
|
||||
```
|
||||
npm run build
|
||||
```
|
||||
|
||||
### Run your unit tests
|
||||
```
|
||||
npm run test:unit
|
||||
```
|
||||
|
||||
### Lints and fixes files
|
||||
```
|
||||
npm run lint
|
||||
```
|
||||
|
||||
### Customize configuration
|
||||
See [Configuration Reference](https://cli.vuejs.org/config/).
|
|
@ -1,9 +0,0 @@
|
|||
module.exports = {
|
||||
presets: [
|
||||
'@vue/cli-plugin-babel/preset'
|
||||
]
|
||||
// plugins: [['import', {
|
||||
// libraryName: 'ant-design-vue',
|
||||
// style: true // or 'css'
|
||||
// }]]
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/logo.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>certd</title>
|
||||
<link rel="stylesheet" type="text/css" href="/index.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="app">
|
||||
<div class="fs-bootstrap">
|
||||
<div class="fs-bootstrap__main">
|
||||
<div class="fs-bootstrap__loading"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,88 +0,0 @@
|
|||
{
|
||||
"name": "@certd/certd-ui",
|
||||
"version": "0.2.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"dev:pm": "vite --mode pm",
|
||||
"dev:force": "vite --force",
|
||||
"debug": "vite --mode debug",
|
||||
"debug:pm": "vite --mode debugpm",
|
||||
"debug:force": "vite --force --mode debug",
|
||||
"build": "vite build ",
|
||||
"serve": "vite preview",
|
||||
"preview": "vite preview",
|
||||
"pretty-quick": "pretty-quick",
|
||||
"lint-fix": "eslint --fix --ext .js --ext .jsx --ext .vue src/",
|
||||
"upgrade": "yarn upgrade-interactive --latest"
|
||||
},
|
||||
"author": "Greper",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@ant-design/colors": "^6.0.0",
|
||||
"@ant-design/icons-vue": "^6.0.1",
|
||||
"ant-design-vue": "^3.2.12",
|
||||
"axios": "^0.27.2",
|
||||
"core-js": "^3.25.4",
|
||||
"dayjs": "^1.11.5",
|
||||
"lodash-es": "^4.17.15",
|
||||
"mitt": "^3.0.0",
|
||||
"vue": "^3.2.40",
|
||||
"vue-i18n": "^9.2.2",
|
||||
"vue-router": "^4.1.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-commonjs": "^22.0.2",
|
||||
"@rollup/plugin-node-resolve": "^14.1.0",
|
||||
"@types/chai": "^4.3.3",
|
||||
"@types/mocha": "^10.0.0",
|
||||
"@types/node": "^18.8.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.38.1",
|
||||
"@typescript-eslint/parser": "^5.38.1",
|
||||
"@vitejs/plugin-legacy": "^2.2.0",
|
||||
"@vitejs/plugin-vue": "^3.1.2",
|
||||
"@vitejs/plugin-vue-jsx": "^2.0.1",
|
||||
"@vue/compiler-sfc": "^3.2.40",
|
||||
"@vue/eslint-config-typescript": "^11.0.2",
|
||||
"@vue/test-utils": "^2.1.0",
|
||||
"autoprefixer": "^10.4.12",
|
||||
"caller-path": "^4.0.0",
|
||||
"chai": "^4.1.2",
|
||||
"eslint": "^8.24.0",
|
||||
"eslint-config-prettier": "^8.1.0",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"eslint-plugin-promise": "^6.0.1",
|
||||
"eslint-plugin-vue": "^9.5.1",
|
||||
"less": "^4.1.3",
|
||||
"less-loader": "^11.0.0",
|
||||
"lint-staged": "^13.0.3",
|
||||
"postcss": "^8.4.17",
|
||||
"prettier": "2.7.1",
|
||||
"rimraf": "^3.0.2",
|
||||
"rollup": "^2.79.1",
|
||||
"rollup-plugin-visualizer": "^5.8.2",
|
||||
"stylelint": "^14.13.0",
|
||||
"stylelint-config-prettier": "^9.0.3",
|
||||
"stylelint-order": "^5.0.0",
|
||||
"vite": "^3.1.4",
|
||||
"vite-plugin-compression": "^0.5.1",
|
||||
"vite-plugin-optimize-persist": "^0.1.2",
|
||||
"vite-plugin-package-config": "^0.1.1",
|
||||
"vue-eslint-parser": "^9.1.0"
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
"pre-commit": "pretty-quick --staged"
|
||||
}
|
||||
},
|
||||
"gitHead": "9c2162697f3affea22c9a8cbc0ca74f4034ab27e",
|
||||
"vite": {
|
||||
"optimizeDeps": {
|
||||
"include": [
|
||||
"@iconify/iconify"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 7.6 KiB |
Before Width: | Height: | Size: 8.5 KiB |
|
@ -1,17 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
||||
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
||||
</noscript>
|
||||
<div id="app"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
</body>
|
||||
</html>
|
Before Width: | Height: | Size: 4.2 KiB |
|
@ -1,7 +0,0 @@
|
|||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||
width="500" height="500" viewBox="0 0 500.000000 500.000000"
|
||||
>
|
||||
<path d="M28.34 56.68h28.34V36.12H28.34a7.79 7.79 0 1 1 0-15.58h19.84v9.05h8.5V12H28.34a16.29 16.29 0 0 0 0 32.58h19.84v3.56H28.34a19.84 19.84 0 0 1 0-39.68h28.34V0H28.34a28.34 28.34 0 0 0 0 56.68z"
|
||||
transform="translate(70, 76) scale(6,6)"
|
||||
></path>
|
||||
</svg>
|
Before Width: | Height: | Size: 402 B |
|
@ -1,44 +0,0 @@
|
|||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||
width="800" height="300" viewBox="0 0 800.000000 300.000000"
|
||||
>
|
||||
|
||||
<g fill="#333">
|
||||
<path d="M28.34 56.68h28.34V36.12H28.34a7.79 7.79 0 1 1 0-15.58h19.84v9.05h8.5V12H28.34a16.29 16.29 0 0 0 0 32.58h19.84v3.56H28.34a19.84 19.84 0 0 1 0-39.68h28.34V0H28.34a28.34 28.34 0 0 0 0 56.68z"
|
||||
transform="translate(40, 40) scale(4,4)"
|
||||
></path>
|
||||
<g transform="translate(280, 260) scale(2,2)">
|
||||
<path d="M28.95-58.70L49.98-58.70L49.98-48.22L33.70-48.22Q27.37-48.22 24.46-47.34Q21.56-46.46 19.62-43.91L19.62-43.91Q18.30-42.15 17.82-40.39Q17.34-38.63 16.98-34.41L16.98-34.41L49.98-34.41L49.98-23.94L16.98-23.94Q17.69-16.37 21.47-13.42Q25.26-10.47 34.32-10.47L34.32-10.47L49.98-10.47L49.98 0L33.70 0Q27.10 0 22.09-0.79L22.09-0.79Q14.17-2.11 9.50-7.74L9.50-7.74Q2.82-15.84 2.82-29.66L2.82-29.66Q2.82-44.97 12.23-53.50L12.23-53.50Q15.49-56.41 19.14-57.55Q22.79-58.70 28.95-58.70L28.95-58.70Z"
|
||||
transform="translate(0 0) "
|
||||
|
||||
></path>
|
||||
<path d="M28.51-22.26L18.48-22.26L18.48 0L5.98 0L5.98-58.70L34.67-58.70Q46.99-58.70 51.83-55.53L51.83-55.53Q55.18-53.42 56.98-49.94Q58.78-46.46 58.78-42.33L58.78-42.33Q58.78-33.97 54.56-29.39L54.56-29.39Q51.92-26.66 47.61-25.26L47.61-25.26Q51.04-24.02 52.80-22.66Q54.56-21.30 55.97-18.66L55.97-18.66Q57.02-16.54 57.51-14.61Q57.99-12.67 58.26-8.89L58.26-8.89Q58.78-2.55 59.66 0L59.66 0L45.67 0Q45.06-2.02 44.35-8.36L44.35-8.36Q43.91-13.46 42.55-16.19Q41.18-18.92 38.46-20.50L38.46-20.50Q35.02-22.35 28.51-22.26L28.51-22.26ZM18.48-48.22L18.48-32.74L35.99-32.74Q40.39-32.74 42.24-34.06L42.24-34.06Q45.06-35.99 45.06-40.83L45.06-40.83Q45.06-46.20 40.83-47.70L40.83-47.70Q39.34-48.22 35.99-48.22L35.99-48.22L18.48-48.22Z"
|
||||
transform="translate(58.855999999999995 0) "
|
||||
|
||||
></path>
|
||||
<path d="M19.01 0L19.01-48.22L0.35-48.22L0.35-58.70L50.95-58.70L50.95-48.22L31.50-48.22L31.50 0L19.01 0Z"
|
||||
transform="translate(126.68799999999999 0) "
|
||||
></path>
|
||||
<path d="M5.98 0L5.98-58.70L30.89-58.70Q40.22-58.70 45.32-56.85L45.32-56.85Q54.74-53.42 57.90-44.26L57.90-44.26Q60.28-37.22 60.28-29.22L60.28-29.22Q60.28-21.30 57.99-14.26L57.99-14.26Q55.70-7.04 50.42-3.61L50.42-3.61Q47.08-1.50 43.08-0.75Q39.07 0 30.89 0L30.89 0L5.98 0ZM30.89-48.22L18.48-48.22L18.48-10.47L30.89-10.47Q39.07-10.47 42.24-14.08L42.24-14.08Q44.18-16.37 45.36-20.50Q46.55-24.64 46.55-29.30L46.55-29.30Q46.55-34.50 45.14-38.81Q43.74-43.12 41.45-45.23L41.45-45.23Q38.10-48.22 30.89-48.22L30.89-48.22Z"
|
||||
transform="translate(183.07999999999998 0) "
|
||||
></path>
|
||||
</g>
|
||||
<!-- <path d="M13.00-21.91L21.24-21.91L21.24-17.23L14.04-17.23Q10.39-17.23-->
|
||||
<!-- 9-15.62L9-15.62Q7.65-14.08-->
|
||||
<!-- 7.65-10.93L7.65-10.93Q7.65-7.42 9.86-5.80L9.86-5.80Q10.75-5.17-->
|
||||
<!-- 11.81-4.93Q12.87-4.68-->
|
||||
<!-- 14.76-4.68L14.76-4.68L21.24-4.68L21.24-->
|
||||
<!-- 0L13.00 0Q9.67 0 7.74-0.67Q5.80-1.35-->
|
||||
<!-- 4.32-3.01L4.32-3.01Q1.48-6.17-->
|
||||
<!-- 1.48-11.03L1.48-11.03Q1.48-16.88-->
|
||||
<!-- 4.86-19.75L4.86-19.75Q6.21-20.93-->
|
||||
<!-- 8.10-21.42Q9.99-21.91-->
|
||||
<!-- 13.00-21.91L13.00-21.91ZM31.05-13.32L43.74-13.32L43.74-8.64L31.05-8.64Q31.23-6.48-->
|
||||
<!-- 32.44-5.58Q33.66-4.68 36.41-4.68L36.41-4.68L43.74-4.68L43.74 0L35.73 0Q33.12 0 31.48-0.47Q29.83-0.94 28.39-2.02L28.39-2.02Q24.39-5.13 24.39-11.25L24.39-11.25Q24.39-15.21 26.50-18.18L26.50-18.18Q27.94-20.20 29.97-21.06Q31.99-21.91 35.28-21.91L35.28-21.91L43.74-21.91L43.74-17.23L35.73-17.23Q33.25-17.23 32.27-16.40Q31.27-15.57 31.05-13.32L31.05-13.32ZM48.64 0L48.64-21.91L57.55-21.91Q60.30-21.91 61.81-21.53Q63.31-21.15 64.31-20.25L64.31-20.25Q65.30-19.35 65.70-18Q66.10-16.65 66.10-14.13L66.10-14.13L66.10-12.01L60.30-12.01L60.30-13.18Q60.30-15.52 59.49-16.38Q58.68-17.23 56.38-17.23L56.38-17.23L54.67-17.23L54.67 0L48.64 0ZM67.50-21.91L71.33-21.91L71.33-30.02L77.36-30.02L77.36-21.91L82.94-21.91L82.94-17.23L77.36-17.23L77.36-9.27Q77.36-6.48 77.85-5.76L77.85-5.76Q78.61-4.68 80.55-4.68L80.55-4.68L82.94-4.68L82.94 0L78.57 0Q74.66 0 72.99-1.89Q71.33-3.78 71.33-8.23L71.33-8.23L71.33-17.23L67.50-17.23L67.50-21.91ZM96.08-21.91L101.75-21.91L101.75-30.02L107.73-30.02L107.73 0L97.38 0Q94.23 0 92.61-0.49L92.61-0.49Q88.78-1.71 86.90-5.26L86.90-5.26Q85.59-7.65 85.59-11.12L85.59-11.12Q85.59-16.74 89.37-19.84L89.37-19.84Q91.84-21.91 96.08-21.91L96.08-21.91ZM97.38-4.68L101.75-4.68L101.75-17.23L97.38-17.23Q94.50-17.23 93.02-15.30L93.02-15.30Q91.71-13.68 91.71-11.12L91.71-11.12Q91.71-7.38 93.87-5.76L93.87-5.76Q95.36-4.68 97.38-4.68L97.38-4.68Z"-->
|
||||
<!-- fill="#2c3e50"-->
|
||||
<!-- transform="translate(300, 270) scale(4,4)"-->
|
||||
|
||||
<!-- ></path>-->
|
||||
<text x="300" y="100" font-size="50" font-weight="bold">让你的证书永不过期</text>
|
||||
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 4.7 KiB |
|
@ -1,44 +0,0 @@
|
|||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||
width="800" height="300" viewBox="0 0 800.000000 300.000000"
|
||||
>
|
||||
|
||||
<g fill="#fff">
|
||||
<path d="M28.34 56.68h28.34V36.12H28.34a7.79 7.79 0 1 1 0-15.58h19.84v9.05h8.5V12H28.34a16.29 16.29 0 0 0 0 32.58h19.84v3.56H28.34a19.84 19.84 0 0 1 0-39.68h28.34V0H28.34a28.34 28.34 0 0 0 0 56.68z"
|
||||
transform="translate(40, 40) scale(4,4)"
|
||||
></path>
|
||||
<g transform="translate(280, 260) scale(2,2)">
|
||||
<path d="M28.95-58.70L49.98-58.70L49.98-48.22L33.70-48.22Q27.37-48.22 24.46-47.34Q21.56-46.46 19.62-43.91L19.62-43.91Q18.30-42.15 17.82-40.39Q17.34-38.63 16.98-34.41L16.98-34.41L49.98-34.41L49.98-23.94L16.98-23.94Q17.69-16.37 21.47-13.42Q25.26-10.47 34.32-10.47L34.32-10.47L49.98-10.47L49.98 0L33.70 0Q27.10 0 22.09-0.79L22.09-0.79Q14.17-2.11 9.50-7.74L9.50-7.74Q2.82-15.84 2.82-29.66L2.82-29.66Q2.82-44.97 12.23-53.50L12.23-53.50Q15.49-56.41 19.14-57.55Q22.79-58.70 28.95-58.70L28.95-58.70Z"
|
||||
transform="translate(0 0) "
|
||||
|
||||
></path>
|
||||
<path d="M28.51-22.26L18.48-22.26L18.48 0L5.98 0L5.98-58.70L34.67-58.70Q46.99-58.70 51.83-55.53L51.83-55.53Q55.18-53.42 56.98-49.94Q58.78-46.46 58.78-42.33L58.78-42.33Q58.78-33.97 54.56-29.39L54.56-29.39Q51.92-26.66 47.61-25.26L47.61-25.26Q51.04-24.02 52.80-22.66Q54.56-21.30 55.97-18.66L55.97-18.66Q57.02-16.54 57.51-14.61Q57.99-12.67 58.26-8.89L58.26-8.89Q58.78-2.55 59.66 0L59.66 0L45.67 0Q45.06-2.02 44.35-8.36L44.35-8.36Q43.91-13.46 42.55-16.19Q41.18-18.92 38.46-20.50L38.46-20.50Q35.02-22.35 28.51-22.26L28.51-22.26ZM18.48-48.22L18.48-32.74L35.99-32.74Q40.39-32.74 42.24-34.06L42.24-34.06Q45.06-35.99 45.06-40.83L45.06-40.83Q45.06-46.20 40.83-47.70L40.83-47.70Q39.34-48.22 35.99-48.22L35.99-48.22L18.48-48.22Z"
|
||||
transform="translate(58.855999999999995 0) "
|
||||
|
||||
></path>
|
||||
<path d="M19.01 0L19.01-48.22L0.35-48.22L0.35-58.70L50.95-58.70L50.95-48.22L31.50-48.22L31.50 0L19.01 0Z"
|
||||
transform="translate(126.68799999999999 0) "
|
||||
></path>
|
||||
<path d="M5.98 0L5.98-58.70L30.89-58.70Q40.22-58.70 45.32-56.85L45.32-56.85Q54.74-53.42 57.90-44.26L57.90-44.26Q60.28-37.22 60.28-29.22L60.28-29.22Q60.28-21.30 57.99-14.26L57.99-14.26Q55.70-7.04 50.42-3.61L50.42-3.61Q47.08-1.50 43.08-0.75Q39.07 0 30.89 0L30.89 0L5.98 0ZM30.89-48.22L18.48-48.22L18.48-10.47L30.89-10.47Q39.07-10.47 42.24-14.08L42.24-14.08Q44.18-16.37 45.36-20.50Q46.55-24.64 46.55-29.30L46.55-29.30Q46.55-34.50 45.14-38.81Q43.74-43.12 41.45-45.23L41.45-45.23Q38.10-48.22 30.89-48.22L30.89-48.22Z"
|
||||
transform="translate(183.07999999999998 0) "
|
||||
></path>
|
||||
</g>
|
||||
<!-- <path d="M13.00-21.91L21.24-21.91L21.24-17.23L14.04-17.23Q10.39-17.23-->
|
||||
<!-- 9-15.62L9-15.62Q7.65-14.08-->
|
||||
<!-- 7.65-10.93L7.65-10.93Q7.65-7.42 9.86-5.80L9.86-5.80Q10.75-5.17-->
|
||||
<!-- 11.81-4.93Q12.87-4.68-->
|
||||
<!-- 14.76-4.68L14.76-4.68L21.24-4.68L21.24-->
|
||||
<!-- 0L13.00 0Q9.67 0 7.74-0.67Q5.80-1.35-->
|
||||
<!-- 4.32-3.01L4.32-3.01Q1.48-6.17-->
|
||||
<!-- 1.48-11.03L1.48-11.03Q1.48-16.88-->
|
||||
<!-- 4.86-19.75L4.86-19.75Q6.21-20.93-->
|
||||
<!-- 8.10-21.42Q9.99-21.91-->
|
||||
<!-- 13.00-21.91L13.00-21.91ZM31.05-13.32L43.74-13.32L43.74-8.64L31.05-8.64Q31.23-6.48-->
|
||||
<!-- 32.44-5.58Q33.66-4.68 36.41-4.68L36.41-4.68L43.74-4.68L43.74 0L35.73 0Q33.12 0 31.48-0.47Q29.83-0.94 28.39-2.02L28.39-2.02Q24.39-5.13 24.39-11.25L24.39-11.25Q24.39-15.21 26.50-18.18L26.50-18.18Q27.94-20.20 29.97-21.06Q31.99-21.91 35.28-21.91L35.28-21.91L43.74-21.91L43.74-17.23L35.73-17.23Q33.25-17.23 32.27-16.40Q31.27-15.57 31.05-13.32L31.05-13.32ZM48.64 0L48.64-21.91L57.55-21.91Q60.30-21.91 61.81-21.53Q63.31-21.15 64.31-20.25L64.31-20.25Q65.30-19.35 65.70-18Q66.10-16.65 66.10-14.13L66.10-14.13L66.10-12.01L60.30-12.01L60.30-13.18Q60.30-15.52 59.49-16.38Q58.68-17.23 56.38-17.23L56.38-17.23L54.67-17.23L54.67 0L48.64 0ZM67.50-21.91L71.33-21.91L71.33-30.02L77.36-30.02L77.36-21.91L82.94-21.91L82.94-17.23L77.36-17.23L77.36-9.27Q77.36-6.48 77.85-5.76L77.85-5.76Q78.61-4.68 80.55-4.68L80.55-4.68L82.94-4.68L82.94 0L78.57 0Q74.66 0 72.99-1.89Q71.33-3.78 71.33-8.23L71.33-8.23L71.33-17.23L67.50-17.23L67.50-21.91ZM96.08-21.91L101.75-21.91L101.75-30.02L107.73-30.02L107.73 0L97.38 0Q94.23 0 92.61-0.49L92.61-0.49Q88.78-1.71 86.90-5.26L86.90-5.26Q85.59-7.65 85.59-11.12L85.59-11.12Q85.59-16.74 89.37-19.84L89.37-19.84Q91.84-21.91 96.08-21.91L96.08-21.91ZM97.38-4.68L101.75-4.68L101.75-17.23L97.38-17.23Q94.50-17.23 93.02-15.30L93.02-15.30Q91.71-13.68 91.71-11.12L91.71-11.12Q91.71-7.38 93.87-5.76L93.87-5.76Q95.36-4.68 97.38-4.68L97.38-4.68Z"-->
|
||||
<!-- fill="#2c3e50"-->
|
||||
<!-- transform="translate(300, 270) scale(4,4)"-->
|
||||
|
||||
<!-- ></path>-->
|
||||
<text x="300" y="100" font-size="50" font-weight="bold">让你的证书永不过期</text>
|
||||
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 4.7 KiB |
|
@ -1,17 +0,0 @@
|
|||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||
width="500" height="500" viewBox="0 0 500.000000 500.000000"
|
||||
>
|
||||
|
||||
|
||||
|
||||
<path d="M28.34 56.68h28.34V36.12H28.34a7.79 7.79 0 1 1 0-15.58h19.84v9.05h8.5V12H28.34a16.29 16.29 0 0 0 0 32.58h19.84v3.56H28.34a19.84 19.84 0 0 1 0-39.68h28.34V0H28.34a28.34 28.34 0 0 0 0 56.68z"
|
||||
fill="#2c3e50"
|
||||
transform="translate(124, 60) scale(4,4)"
|
||||
></path>
|
||||
<path d="M13.00-21.91L21.24-21.91L21.24-17.23L14.04-17.23Q10.39-17.23 9-15.62L9-15.62Q7.65-14.08 7.65-10.93L7.65-10.93Q7.65-7.42 9.86-5.80L9.86-5.80Q10.75-5.17 11.81-4.93Q12.87-4.68 14.76-4.68L14.76-4.68L21.24-4.68L21.24 0L13.00 0Q9.67 0 7.74-0.67Q5.80-1.35 4.32-3.01L4.32-3.01Q1.48-6.17 1.48-11.03L1.48-11.03Q1.48-16.88 4.86-19.75L4.86-19.75Q6.21-20.93 8.10-21.42Q9.99-21.91 13.00-21.91L13.00-21.91ZM31.05-13.32L43.74-13.32L43.74-8.64L31.05-8.64Q31.23-6.48 32.44-5.58Q33.66-4.68 36.41-4.68L36.41-4.68L43.74-4.68L43.74 0L35.73 0Q33.12 0 31.48-0.47Q29.83-0.94 28.39-2.02L28.39-2.02Q24.39-5.13 24.39-11.25L24.39-11.25Q24.39-15.21 26.50-18.18L26.50-18.18Q27.94-20.20 29.97-21.06Q31.99-21.91 35.28-21.91L35.28-21.91L43.74-21.91L43.74-17.23L35.73-17.23Q33.25-17.23 32.27-16.40Q31.27-15.57 31.05-13.32L31.05-13.32ZM48.64 0L48.64-21.91L57.55-21.91Q60.30-21.91 61.81-21.53Q63.31-21.15 64.31-20.25L64.31-20.25Q65.30-19.35 65.70-18Q66.10-16.65 66.10-14.13L66.10-14.13L66.10-12.01L60.30-12.01L60.30-13.18Q60.30-15.52 59.49-16.38Q58.68-17.23 56.38-17.23L56.38-17.23L54.67-17.23L54.67 0L48.64 0ZM67.50-21.91L71.33-21.91L71.33-30.02L77.36-30.02L77.36-21.91L82.94-21.91L82.94-17.23L77.36-17.23L77.36-9.27Q77.36-6.48 77.85-5.76L77.85-5.76Q78.61-4.68 80.55-4.68L80.55-4.68L82.94-4.68L82.94 0L78.57 0Q74.66 0 72.99-1.89Q71.33-3.78 71.33-8.23L71.33-8.23L71.33-17.23L67.50-17.23L67.50-21.91ZM96.08-21.91L101.75-21.91L101.75-30.02L107.73-30.02L107.73 0L97.38 0Q94.23 0 92.61-0.49L92.61-0.49Q88.78-1.71 86.90-5.26L86.90-5.26Q85.59-7.65 85.59-11.12L85.59-11.12Q85.59-16.74 89.37-19.84L89.37-19.84Q91.84-21.91 96.08-21.91L96.08-21.91ZM97.38-4.68L101.75-4.68L101.75-17.23L97.38-17.23Q94.50-17.23 93.02-15.30L93.02-15.30Q91.71-13.68 91.71-11.12L91.71-11.12Q91.71-7.38 93.87-5.76L93.87-5.76Q95.36-4.68 97.38-4.68L97.38-4.68Z"
|
||||
fill="#2c3e50"
|
||||
transform="translate(28, 430) scale(4,4)"
|
||||
|
||||
></path>
|
||||
|
||||
</svg>
|
Before Width: | Height: | Size: 2.3 KiB |
|
@ -1,7 +0,0 @@
|
|||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||
width="500" height="500" viewBox="0 0 500.000000 500.000000"
|
||||
>
|
||||
<path d="M28.34 56.68h28.34V36.12H28.34a7.79 7.79 0 1 1 0-15.58h19.84v9.05h8.5V12H28.34a16.29 16.29 0 0 0 0 32.58h19.84v3.56H28.34a19.84 19.84 0 0 1 0-39.68h28.34V0H28.34a28.34 28.34 0 0 0 0 56.68z"
|
||||
transform="translate(70, 76) scale(6,6)"
|
||||
></path>
|
||||
</svg>
|
Before Width: | Height: | Size: 402 B |
|
@ -1,108 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="210mm"
|
||||
height="210mm"
|
||||
viewBox="0 0 210 210"
|
||||
version="1.1"
|
||||
id="svg8">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<g
|
||||
id="layer1"
|
||||
style="display:inline">
|
||||
<path
|
||||
style="fill:#002255;stroke:none;stroke-width:0.625348"
|
||||
d="M 35.587501,69.766667 V 59.766664 h 70.000109 69.99991 v 10.000003 9.999997 H 105.58761 35.587501 Z"
|
||||
id="path12" />
|
||||
<rect
|
||||
style="fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
|
||||
id="rect22-2"
|
||||
width="32.244232"
|
||||
height="20"
|
||||
x="71.506088"
|
||||
y="106.64581" />
|
||||
<rect
|
||||
style="fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
|
||||
id="rect22-8-8"
|
||||
width="32.244232"
|
||||
height="20"
|
||||
x="107.42467"
|
||||
y="106.64581" />
|
||||
<rect
|
||||
style="fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
|
||||
id="rect22-8-5-8"
|
||||
width="32.244232"
|
||||
height="20"
|
||||
x="143.34325"
|
||||
y="106.64581" />
|
||||
<rect
|
||||
style="fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
|
||||
id="rect22-2-4"
|
||||
width="32.244232"
|
||||
height="20"
|
||||
x="71.506088"
|
||||
y="129.82079" />
|
||||
<rect
|
||||
style="fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
|
||||
id="rect22-8-8-3"
|
||||
width="32.244232"
|
||||
height="20"
|
||||
x="107.42467"
|
||||
y="129.82079" />
|
||||
<rect
|
||||
style="fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
|
||||
id="rect22-8-5-8-2"
|
||||
width="32.244232"
|
||||
height="20"
|
||||
x="143.34325"
|
||||
y="129.82079" />
|
||||
<rect
|
||||
style="fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
|
||||
id="rect22-2-7"
|
||||
width="32.244232"
|
||||
height="20"
|
||||
x="35.587502"
|
||||
y="106.64581" />
|
||||
<rect
|
||||
style="fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
|
||||
id="rect22-2-4-0"
|
||||
width="32.244232"
|
||||
height="20"
|
||||
x="35.587502"
|
||||
y="129.82079" />
|
||||
<rect
|
||||
style="display:inline;fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
|
||||
id="rect22-2-9"
|
||||
width="32.244232"
|
||||
height="20"
|
||||
x="71.506088"
|
||||
y="82.941666" />
|
||||
<rect
|
||||
style="display:inline;fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
|
||||
id="rect22-8-8-37"
|
||||
width="32.244232"
|
||||
height="20"
|
||||
x="107.42467"
|
||||
y="82.941666" />
|
||||
<rect
|
||||
style="display:inline;fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
|
||||
id="rect22-8-5-8-4"
|
||||
width="32.244232"
|
||||
height="20"
|
||||
x="143.34325"
|
||||
y="82.941666" />
|
||||
<rect
|
||||
style="display:inline;fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
|
||||
id="rect22-2-7-1"
|
||||
width="32.244232"
|
||||
height="20"
|
||||
x="35.587502"
|
||||
y="82.941666" />
|
||||
</g>
|
||||
<polygon
|
||||
points="75.3,174.4 103.1,103.6 79.8,103.6 112.6,41.3 156.4,41.3 129.9,90.5 148.1,90.5 "
|
||||
fill="#f6cc00"
|
||||
id="polygon276"
|
||||
transform="matrix(1.0930933,0,0,0.99853202,-17.517362,-0.52287941)" />
|
||||
</svg>
|
Before Width: | Height: | Size: 3.8 KiB |
|
@ -1,44 +0,0 @@
|
|||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||
width="800" height="300" viewBox="0 0 800.000000 300.000000"
|
||||
>
|
||||
|
||||
<g fill="#fff">
|
||||
<path d="M28.34 56.68h28.34V36.12H28.34a7.79 7.79 0 1 1 0-15.58h19.84v9.05h8.5V12H28.34a16.29 16.29 0 0 0 0 32.58h19.84v3.56H28.34a19.84 19.84 0 0 1 0-39.68h28.34V0H28.34a28.34 28.34 0 0 0 0 56.68z"
|
||||
transform="translate(40, 40) scale(4,4)"
|
||||
></path>
|
||||
<g transform="translate(280, 260) scale(2,2)">
|
||||
<path d="M28.95-58.70L49.98-58.70L49.98-48.22L33.70-48.22Q27.37-48.22 24.46-47.34Q21.56-46.46 19.62-43.91L19.62-43.91Q18.30-42.15 17.82-40.39Q17.34-38.63 16.98-34.41L16.98-34.41L49.98-34.41L49.98-23.94L16.98-23.94Q17.69-16.37 21.47-13.42Q25.26-10.47 34.32-10.47L34.32-10.47L49.98-10.47L49.98 0L33.70 0Q27.10 0 22.09-0.79L22.09-0.79Q14.17-2.11 9.50-7.74L9.50-7.74Q2.82-15.84 2.82-29.66L2.82-29.66Q2.82-44.97 12.23-53.50L12.23-53.50Q15.49-56.41 19.14-57.55Q22.79-58.70 28.95-58.70L28.95-58.70Z"
|
||||
transform="translate(0 0) "
|
||||
|
||||
></path>
|
||||
<path d="M28.51-22.26L18.48-22.26L18.48 0L5.98 0L5.98-58.70L34.67-58.70Q46.99-58.70 51.83-55.53L51.83-55.53Q55.18-53.42 56.98-49.94Q58.78-46.46 58.78-42.33L58.78-42.33Q58.78-33.97 54.56-29.39L54.56-29.39Q51.92-26.66 47.61-25.26L47.61-25.26Q51.04-24.02 52.80-22.66Q54.56-21.30 55.97-18.66L55.97-18.66Q57.02-16.54 57.51-14.61Q57.99-12.67 58.26-8.89L58.26-8.89Q58.78-2.55 59.66 0L59.66 0L45.67 0Q45.06-2.02 44.35-8.36L44.35-8.36Q43.91-13.46 42.55-16.19Q41.18-18.92 38.46-20.50L38.46-20.50Q35.02-22.35 28.51-22.26L28.51-22.26ZM18.48-48.22L18.48-32.74L35.99-32.74Q40.39-32.74 42.24-34.06L42.24-34.06Q45.06-35.99 45.06-40.83L45.06-40.83Q45.06-46.20 40.83-47.70L40.83-47.70Q39.34-48.22 35.99-48.22L35.99-48.22L18.48-48.22Z"
|
||||
transform="translate(58.855999999999995 0) "
|
||||
|
||||
></path>
|
||||
<path d="M19.01 0L19.01-48.22L0.35-48.22L0.35-58.70L50.95-58.70L50.95-48.22L31.50-48.22L31.50 0L19.01 0Z"
|
||||
transform="translate(126.68799999999999 0) "
|
||||
></path>
|
||||
<path d="M5.98 0L5.98-58.70L30.89-58.70Q40.22-58.70 45.32-56.85L45.32-56.85Q54.74-53.42 57.90-44.26L57.90-44.26Q60.28-37.22 60.28-29.22L60.28-29.22Q60.28-21.30 57.99-14.26L57.99-14.26Q55.70-7.04 50.42-3.61L50.42-3.61Q47.08-1.50 43.08-0.75Q39.07 0 30.89 0L30.89 0L5.98 0ZM30.89-48.22L18.48-48.22L18.48-10.47L30.89-10.47Q39.07-10.47 42.24-14.08L42.24-14.08Q44.18-16.37 45.36-20.50Q46.55-24.64 46.55-29.30L46.55-29.30Q46.55-34.50 45.14-38.81Q43.74-43.12 41.45-45.23L41.45-45.23Q38.10-48.22 30.89-48.22L30.89-48.22Z"
|
||||
transform="translate(183.07999999999998 0) "
|
||||
></path>
|
||||
</g>
|
||||
<!-- <path d="M13.00-21.91L21.24-21.91L21.24-17.23L14.04-17.23Q10.39-17.23-->
|
||||
<!-- 9-15.62L9-15.62Q7.65-14.08-->
|
||||
<!-- 7.65-10.93L7.65-10.93Q7.65-7.42 9.86-5.80L9.86-5.80Q10.75-5.17-->
|
||||
<!-- 11.81-4.93Q12.87-4.68-->
|
||||
<!-- 14.76-4.68L14.76-4.68L21.24-4.68L21.24-->
|
||||
<!-- 0L13.00 0Q9.67 0 7.74-0.67Q5.80-1.35-->
|
||||
<!-- 4.32-3.01L4.32-3.01Q1.48-6.17-->
|
||||
<!-- 1.48-11.03L1.48-11.03Q1.48-16.88-->
|
||||
<!-- 4.86-19.75L4.86-19.75Q6.21-20.93-->
|
||||
<!-- 8.10-21.42Q9.99-21.91-->
|
||||
<!-- 13.00-21.91L13.00-21.91ZM31.05-13.32L43.74-13.32L43.74-8.64L31.05-8.64Q31.23-6.48-->
|
||||
<!-- 32.44-5.58Q33.66-4.68 36.41-4.68L36.41-4.68L43.74-4.68L43.74 0L35.73 0Q33.12 0 31.48-0.47Q29.83-0.94 28.39-2.02L28.39-2.02Q24.39-5.13 24.39-11.25L24.39-11.25Q24.39-15.21 26.50-18.18L26.50-18.18Q27.94-20.20 29.97-21.06Q31.99-21.91 35.28-21.91L35.28-21.91L43.74-21.91L43.74-17.23L35.73-17.23Q33.25-17.23 32.27-16.40Q31.27-15.57 31.05-13.32L31.05-13.32ZM48.64 0L48.64-21.91L57.55-21.91Q60.30-21.91 61.81-21.53Q63.31-21.15 64.31-20.25L64.31-20.25Q65.30-19.35 65.70-18Q66.10-16.65 66.10-14.13L66.10-14.13L66.10-12.01L60.30-12.01L60.30-13.18Q60.30-15.52 59.49-16.38Q58.68-17.23 56.38-17.23L56.38-17.23L54.67-17.23L54.67 0L48.64 0ZM67.50-21.91L71.33-21.91L71.33-30.02L77.36-30.02L77.36-21.91L82.94-21.91L82.94-17.23L77.36-17.23L77.36-9.27Q77.36-6.48 77.85-5.76L77.85-5.76Q78.61-4.68 80.55-4.68L80.55-4.68L82.94-4.68L82.94 0L78.57 0Q74.66 0 72.99-1.89Q71.33-3.78 71.33-8.23L71.33-8.23L71.33-17.23L67.50-17.23L67.50-21.91ZM96.08-21.91L101.75-21.91L101.75-30.02L107.73-30.02L107.73 0L97.38 0Q94.23 0 92.61-0.49L92.61-0.49Q88.78-1.71 86.90-5.26L86.90-5.26Q85.59-7.65 85.59-11.12L85.59-11.12Q85.59-16.74 89.37-19.84L89.37-19.84Q91.84-21.91 96.08-21.91L96.08-21.91ZM97.38-4.68L101.75-4.68L101.75-17.23L97.38-17.23Q94.50-17.23 93.02-15.30L93.02-15.30Q91.71-13.68 91.71-11.12L91.71-11.12Q91.71-7.38 93.87-5.76L93.87-5.76Q95.36-4.68 97.38-4.68L97.38-4.68Z"-->
|
||||
<!-- fill="#2c3e50"-->
|
||||
<!-- transform="translate(300, 270) scale(4,4)"-->
|
||||
|
||||
<!-- ></path>-->
|
||||
<text x="300" y="100" font-size="50" font-weight="bold">让你的证书永不过期</text>
|
||||
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 4.7 KiB |
|
@ -1,106 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="210mm"
|
||||
height="210mm"
|
||||
viewBox="0 0 210 210"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
>
|
||||
<g id="layer1" style="display:inline">
|
||||
<path
|
||||
style="fill:#002255;stroke:none;stroke-width:0.625348"
|
||||
d="M 35.587501,69.766667 V 59.766664 h 70.000109 69.99991 v 10.000003 9.999997 H 105.58761 35.587501 Z"
|
||||
id="path12" />
|
||||
<rect
|
||||
style="fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
|
||||
id="rect22-2"
|
||||
width="32.244232"
|
||||
height="20"
|
||||
x="71.506088"
|
||||
y="106.64581" />
|
||||
<rect
|
||||
style="fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
|
||||
id="rect22-8-8"
|
||||
width="32.244232"
|
||||
height="20"
|
||||
x="107.42467"
|
||||
y="106.64581" />
|
||||
<rect
|
||||
style="fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
|
||||
id="rect22-8-5-8"
|
||||
width="32.244232"
|
||||
height="20"
|
||||
x="143.34325"
|
||||
y="106.64581" />
|
||||
<rect
|
||||
style="fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
|
||||
id="rect22-2-4"
|
||||
width="32.244232"
|
||||
height="20"
|
||||
x="71.506088"
|
||||
y="129.82079" />
|
||||
<rect
|
||||
style="fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
|
||||
id="rect22-8-8-3"
|
||||
width="32.244232"
|
||||
height="20"
|
||||
x="107.42467"
|
||||
y="129.82079" />
|
||||
<rect
|
||||
style="fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
|
||||
id="rect22-8-5-8-2"
|
||||
width="32.244232"
|
||||
height="20"
|
||||
x="143.34325"
|
||||
y="129.82079" />
|
||||
<rect
|
||||
style="fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
|
||||
id="rect22-2-7"
|
||||
width="32.244232"
|
||||
height="20"
|
||||
x="35.587502"
|
||||
y="106.64581" />
|
||||
<rect
|
||||
style="fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
|
||||
id="rect22-2-4-0"
|
||||
width="32.244232"
|
||||
height="20"
|
||||
x="35.587502"
|
||||
y="129.82079" />
|
||||
<rect
|
||||
style="display:inline;fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
|
||||
id="rect22-2-9"
|
||||
width="32.244232"
|
||||
height="20"
|
||||
x="71.506088"
|
||||
y="82.941666" />
|
||||
<rect
|
||||
style="display:inline;fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
|
||||
id="rect22-8-8-37"
|
||||
width="32.244232"
|
||||
height="20"
|
||||
x="107.42467"
|
||||
y="82.941666" />
|
||||
<rect
|
||||
style="display:inline;fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
|
||||
id="rect22-8-5-8-4"
|
||||
width="32.244232"
|
||||
height="20"
|
||||
x="143.34325"
|
||||
y="82.941666" />
|
||||
<rect
|
||||
style="display:inline;fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
|
||||
id="rect22-2-7-1"
|
||||
width="32.244232"
|
||||
height="20"
|
||||
x="35.587502"
|
||||
y="82.941666" />
|
||||
</g>
|
||||
<polygon
|
||||
points="75.3,174.4 103.1,103.6 79.8,103.6 112.6,41.3 156.4,41.3 129.9,90.5 148.1,90.5 "
|
||||
fill="#f6cc00"
|
||||
id="polygon276"
|
||||
transform="matrix(1.0930933,0,0,0.99853202,-17.517362,-0.52287941)" />
|
||||
|
||||
</svg>
|
Before Width: | Height: | Size: 3.7 KiB |
|
@ -1,12 +0,0 @@
|
|||
html, body, #app { height: 100%; margin: 0; padding: 0; width: 100%;}
|
||||
.fs-bootstrap { background-color: #474949; height: 100%; display: flex; flex-direction: column;position: fixed;width: 100% }
|
||||
.fs-bootstrap__main {flex:1; user-select: none; width: 100%; flex-grow: 1; display: flex; justify-content: center; align-items: center; flex-direction: column; }
|
||||
.fs-bootstrap__footer { width: 100%; flex-grow: 0; text-align: center; padding: 10px 0; }
|
||||
.fs-bootstrap__footer > a { font-size: 12px; color: #ABABAB; text-decoration: none; }
|
||||
.fs-bootstrap__loading {box-sizing: border-box; height: 50px; width: 50px; margin-bottom: 5px;border:5px solid #333333;border-bottom:#aaa 5px solid;
|
||||
border-radius:1000px; animation:load 1.1s infinite linear;-webkit-animation:load 1.1s infinite linear;-moz-animation:load 1.1s infinite linear; -o-animation:load 1.1s infinite linear;
|
||||
}
|
||||
@keyframes load {from {transform:rotate(0deg);-ms-transform:rotate(0deg);}to { transform:rotate(360deg);-ms-transform:rotate(360deg); }
|
||||
}@-webkit-keyframes load {from {-webkit-transform:rotate(0deg); }to { -webkit-transform:rotate(360deg);}
|
||||
}@-moz-keyframes load { from { -moz-transform:rotate(0deg); } to { -moz-transform:rotate(360deg);}
|
||||
}@-o-keyframes load { from { -o-transform:rotate(0deg);} to { -o-transform:rotate(360deg);}}
|
|
@ -1,17 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
||||
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
||||
</noscript>
|
||||
<div id="app"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
</body>
|
||||
</html>
|
|
@ -1,106 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="210mm"
|
||||
height="210mm"
|
||||
viewBox="0 0 210 210"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
>
|
||||
<g id="layer1" style="display:inline">
|
||||
<path
|
||||
style="fill:#002255;stroke:none;stroke-width:0.625348"
|
||||
d="M 35.587501,69.766667 V 59.766664 h 70.000109 69.99991 v 10.000003 9.999997 H 105.58761 35.587501 Z"
|
||||
id="path12" />
|
||||
<rect
|
||||
style="fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
|
||||
id="rect22-2"
|
||||
width="32.244232"
|
||||
height="20"
|
||||
x="71.506088"
|
||||
y="106.64581" />
|
||||
<rect
|
||||
style="fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
|
||||
id="rect22-8-8"
|
||||
width="32.244232"
|
||||
height="20"
|
||||
x="107.42467"
|
||||
y="106.64581" />
|
||||
<rect
|
||||
style="fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
|
||||
id="rect22-8-5-8"
|
||||
width="32.244232"
|
||||
height="20"
|
||||
x="143.34325"
|
||||
y="106.64581" />
|
||||
<rect
|
||||
style="fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
|
||||
id="rect22-2-4"
|
||||
width="32.244232"
|
||||
height="20"
|
||||
x="71.506088"
|
||||
y="129.82079" />
|
||||
<rect
|
||||
style="fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
|
||||
id="rect22-8-8-3"
|
||||
width="32.244232"
|
||||
height="20"
|
||||
x="107.42467"
|
||||
y="129.82079" />
|
||||
<rect
|
||||
style="fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
|
||||
id="rect22-8-5-8-2"
|
||||
width="32.244232"
|
||||
height="20"
|
||||
x="143.34325"
|
||||
y="129.82079" />
|
||||
<rect
|
||||
style="fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
|
||||
id="rect22-2-7"
|
||||
width="32.244232"
|
||||
height="20"
|
||||
x="35.587502"
|
||||
y="106.64581" />
|
||||
<rect
|
||||
style="fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
|
||||
id="rect22-2-4-0"
|
||||
width="32.244232"
|
||||
height="20"
|
||||
x="35.587502"
|
||||
y="129.82079" />
|
||||
<rect
|
||||
style="display:inline;fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
|
||||
id="rect22-2-9"
|
||||
width="32.244232"
|
||||
height="20"
|
||||
x="71.506088"
|
||||
y="82.941666" />
|
||||
<rect
|
||||
style="display:inline;fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
|
||||
id="rect22-8-8-37"
|
||||
width="32.244232"
|
||||
height="20"
|
||||
x="107.42467"
|
||||
y="82.941666" />
|
||||
<rect
|
||||
style="display:inline;fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
|
||||
id="rect22-8-5-8-4"
|
||||
width="32.244232"
|
||||
height="20"
|
||||
x="143.34325"
|
||||
y="82.941666" />
|
||||
<rect
|
||||
style="display:inline;fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
|
||||
id="rect22-2-7-1"
|
||||
width="32.244232"
|
||||
height="20"
|
||||
x="35.587502"
|
||||
y="82.941666" />
|
||||
</g>
|
||||
<polygon
|
||||
points="75.3,174.4 103.1,103.6 79.8,103.6 112.6,41.3 156.4,41.3 129.9,90.5 148.1,90.5 "
|
||||
fill="#f6cc00"
|
||||
id="polygon276"
|
||||
transform="matrix(1.0930933,0,0,0.99853202,-17.517362,-0.52287941)" />
|
||||
|
||||
</svg>
|
Before Width: | Height: | Size: 3.7 KiB |
|
@ -1,38 +0,0 @@
|
|||
<template>
|
||||
<a-config-provider :locale="locale">
|
||||
|
||||
<a-layout class="page-layout">
|
||||
<a-layout-header>Cert-D</a-layout-header>
|
||||
<a-layout style="flex:1">
|
||||
<router-view/>
|
||||
</a-layout>
|
||||
<a-layout-footer>
|
||||
by greper
|
||||
</a-layout-footer>
|
||||
|
||||
</a-layout>
|
||||
|
||||
</a-config-provider>
|
||||
</template>
|
||||
<script>
|
||||
import zhCN from 'ant-design-vue/es/locale/zh_CN'
|
||||
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
locale: zhCN
|
||||
}
|
||||
},
|
||||
setup () {
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="less">
|
||||
.page-layout{
|
||||
height: 100%;
|
||||
overflow-x: hidden;
|
||||
.ant-layout-header{
|
||||
color:#fff;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,86 +0,0 @@
|
|||
import _ from 'lodash'
|
||||
import {
|
||||
AutoComplete,
|
||||
Alert,
|
||||
Avatar,
|
||||
Badge,
|
||||
Button,
|
||||
Calendar,
|
||||
Card,
|
||||
Cascader,
|
||||
Checkbox,
|
||||
Col,
|
||||
DatePicker,
|
||||
Divider,
|
||||
Dropdown,
|
||||
Form,
|
||||
Input,
|
||||
InputNumber,
|
||||
Layout,
|
||||
List,
|
||||
LocaleProvider,
|
||||
Modal,
|
||||
Radio,
|
||||
Row,
|
||||
Select,
|
||||
Switch,
|
||||
Tabs,
|
||||
Tag,
|
||||
TimePicker,
|
||||
Tooltip,
|
||||
Drawer,
|
||||
// ColorPicker,
|
||||
ConfigProvider,
|
||||
Descriptions,
|
||||
Space
|
||||
} from 'ant-design-vue'
|
||||
|
||||
const list = {
|
||||
AutoComplete,
|
||||
Alert,
|
||||
Avatar,
|
||||
Badge,
|
||||
Button,
|
||||
Calendar,
|
||||
Card,
|
||||
Cascader,
|
||||
Checkbox,
|
||||
Col,
|
||||
DatePicker,
|
||||
Divider,
|
||||
Dropdown,
|
||||
Form,
|
||||
Input,
|
||||
InputNumber,
|
||||
Layout,
|
||||
List,
|
||||
LocaleProvider,
|
||||
TimePicker,
|
||||
Modal,
|
||||
Radio,
|
||||
Row,
|
||||
Select,
|
||||
Switch,
|
||||
Tabs,
|
||||
Tag,
|
||||
Tooltip,
|
||||
Drawer,
|
||||
// ColorPicker,
|
||||
ConfigProvider,
|
||||
Descriptions,
|
||||
Space
|
||||
}
|
||||
export default function (app) {
|
||||
_.forEach(list, item => {
|
||||
app.use(item)
|
||||
//
|
||||
// app.config.globalProperties.$message = message
|
||||
// app.config.globalProperties.$notification = notification
|
||||
app.config.globalProperties.$info = Modal.info
|
||||
app.config.globalProperties.$success = Modal.success
|
||||
app.config.globalProperties.$error = Modal.error
|
||||
app.config.globalProperties.$warning = Modal.warning
|
||||
app.config.globalProperties.$confirm = Modal.confirm
|
||||
app.config.globalProperties.$destroyAll = Modal.destroyAll
|
||||
})
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
import { request } from "./service";
|
||||
import inputHandler from "./util.input.handler";
|
||||
|
||||
export default {
|
||||
async list() {
|
||||
const ret = await request({
|
||||
url: "/access-providers/list"
|
||||
});
|
||||
|
||||
inputHandler.handle(ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
};
|
|
@ -1,14 +0,0 @@
|
|||
import { request } from "./service";
|
||||
import inputHandler from "./util.input.handler";
|
||||
|
||||
export default {
|
||||
async list() {
|
||||
const ret = await request({
|
||||
url: "/dns-providers/list"
|
||||
});
|
||||
|
||||
inputHandler.handle(ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
};
|
|
@ -1,40 +0,0 @@
|
|||
import { request } from "./service";
|
||||
import _ from "lodash-es";
|
||||
function arrayToMap(arr) {
|
||||
if (arr && arr instanceof Array) {
|
||||
const map = {};
|
||||
_.forEach(arr, (item) => {
|
||||
map[item.key] = item;
|
||||
});
|
||||
return map;
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
function transfer(options) {
|
||||
options.accessProviders = arrayToMap(options.accessProviders);
|
||||
}
|
||||
export default {
|
||||
exportsToZip(options) {
|
||||
transfer(options);
|
||||
return request({
|
||||
url: "/exports/toZip",
|
||||
data: { options },
|
||||
method: "post",
|
||||
responseType: "blob" // 重点在于配置responseType: 'blob'
|
||||
}).then((res) => {
|
||||
console.log("res", res);
|
||||
const filename = decodeURI(res.headers["content-disposition"].replace("attachment;filename=", "")); // 由后端设置下载文件名
|
||||
const blob = new Blob([res.data], { type: "application/zip" });
|
||||
const a = document.createElement("a");
|
||||
const url = window.URL.createObjectURL(blob);
|
||||
a.href = url;
|
||||
a.download = filename;
|
||||
const body = document.getElementsByTagName("body")[0];
|
||||
body.appendChild(a);
|
||||
a.click();
|
||||
body.removeChild(a);
|
||||
window.URL.revokeObjectURL(url);
|
||||
});
|
||||
}
|
||||
};
|
|
@ -1,14 +0,0 @@
|
|||
import { request } from "./service";
|
||||
import inputHandler from "./util.input.handler";
|
||||
export default {
|
||||
async list() {
|
||||
const ret = await request({
|
||||
url: "/plugins/list"
|
||||
});
|
||||
|
||||
inputHandler.handle(ret);
|
||||
|
||||
console.log("plugins", ret);
|
||||
return ret;
|
||||
}
|
||||
};
|
|
@ -1,15 +0,0 @@
|
|||
import { assign, map } from "lodash";
|
||||
import { service, request } from "./service";
|
||||
|
||||
const files = require.context("./modules", false, /\.js$/);
|
||||
const generators = files.keys().map((key) => files(key).default);
|
||||
|
||||
export default assign(
|
||||
{},
|
||||
...map(generators, (generator) =>
|
||||
generator({
|
||||
service,
|
||||
request
|
||||
})
|
||||
)
|
||||
);
|
|
@ -1,117 +0,0 @@
|
|||
import axios from "axios";
|
||||
import { get } from "lodash-es";
|
||||
import { errorLog, errorCreate } from "./tools";
|
||||
import { env } from "/src/utils/util.env";
|
||||
/**
|
||||
* @description 创建请求实例
|
||||
*/
|
||||
function createService() {
|
||||
// 创建一个 axios 实例
|
||||
const service = axios.create();
|
||||
// 请求拦截
|
||||
service.interceptors.request.use(
|
||||
(config) => config,
|
||||
(error) => {
|
||||
// 发送失败
|
||||
console.log(error);
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
// 响应拦截
|
||||
service.interceptors.response.use(
|
||||
(response) => {
|
||||
console.log("response.config", response.config);
|
||||
if (response.config.responseType === "blob") {
|
||||
return response;
|
||||
}
|
||||
// dataAxios 是 axios 返回数据中的 data
|
||||
const dataAxios = response.data;
|
||||
// 这个状态码是和后端约定的
|
||||
const { code } = dataAxios;
|
||||
// 根据 code 进行判断
|
||||
if (code === undefined) {
|
||||
// 如果没有 code 代表这不是项目后端开发的接口 比如可能是 D2Admin 请求最新版本
|
||||
if (response.config.unpack) {
|
||||
return dataAxios;
|
||||
}
|
||||
return dataAxios.data;
|
||||
} else {
|
||||
// 有 code 代表这是一个后端接口 可以进行进一步的判断
|
||||
switch (code) {
|
||||
case 0:
|
||||
// [ 示例 ] code === 0 代表没有错误
|
||||
return dataAxios.data;
|
||||
default:
|
||||
// 不是正确的 code
|
||||
errorCreate(`${dataAxios.msg}: ${response.config.url}`);
|
||||
return dataAxios;
|
||||
}
|
||||
}
|
||||
},
|
||||
(error) => {
|
||||
const status = get(error, "response.status");
|
||||
switch (status) {
|
||||
case 400:
|
||||
error.message = "请求错误";
|
||||
break;
|
||||
case 401:
|
||||
error.message = "未授权,请登录";
|
||||
break;
|
||||
case 403:
|
||||
error.message = "拒绝访问";
|
||||
break;
|
||||
case 404:
|
||||
error.message = `请求地址出错: ${error.response.config.url}`;
|
||||
break;
|
||||
case 408:
|
||||
error.message = "请求超时";
|
||||
break;
|
||||
case 500:
|
||||
error.message = "服务器内部错误";
|
||||
break;
|
||||
case 501:
|
||||
error.message = "服务未实现";
|
||||
break;
|
||||
case 502:
|
||||
error.message = "网关错误";
|
||||
break;
|
||||
case 503:
|
||||
error.message = "服务不可用";
|
||||
break;
|
||||
case 504:
|
||||
error.message = "网关超时";
|
||||
break;
|
||||
case 505:
|
||||
error.message = "HTTP版本不受支持";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
errorLog(error);
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
return service;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 创建请求方法
|
||||
* @param {Object} service axios 实例
|
||||
*/
|
||||
function createRequestFunction(service) {
|
||||
return function (config) {
|
||||
const configDefault = {
|
||||
headers: {
|
||||
"Content-Type": get(config, "headers.Content-Type", "application/json")
|
||||
},
|
||||
timeout: 5000,
|
||||
baseURL: env.API,
|
||||
data: {}
|
||||
};
|
||||
return service(Object.assign(configDefault, config));
|
||||
};
|
||||
}
|
||||
|
||||
// 用于真实网络请求的实例和请求方法
|
||||
export const service = createService();
|
||||
export const request = createRequestFunction(service);
|
|
@ -1,68 +0,0 @@
|
|||
import { notification } from "ant-design-vue";
|
||||
|
||||
/**
|
||||
* @description 安全地解析 json 字符串
|
||||
* @param {String} jsonString 需要解析的 json 字符串
|
||||
* @param {String} defaultValue 默认值
|
||||
*/
|
||||
export function parse(jsonString = "{}", defaultValue = {}) {
|
||||
let result = defaultValue;
|
||||
try {
|
||||
result = JSON.parse(jsonString);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 接口请求返回
|
||||
* @param {Any} data 返回值
|
||||
* @param {String} msg 状态信息
|
||||
* @param {Number} code 状态码
|
||||
*/
|
||||
export function response(data = {}, msg = "", code = 0) {
|
||||
return [200, { code, msg, data }];
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 接口请求返回 正确返回
|
||||
* @param {Any} data 返回值
|
||||
* @param {String} msg 状态信息
|
||||
*/
|
||||
export function responseSuccess(data = {}, msg = "成功") {
|
||||
return response(data, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 接口请求返回 错误返回
|
||||
* @param {Any} data 返回值
|
||||
* @param {String} msg 状态信息
|
||||
* @param {Number} code 状态码
|
||||
*/
|
||||
export function responseError(data = {}, msg = "请求失败", code = 500) {
|
||||
return response(data, msg, code);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 记录和显示错误
|
||||
* @param {Error} error 错误对象
|
||||
*/
|
||||
export function errorLog(error) {
|
||||
// 打印到控制台
|
||||
console.log(error);
|
||||
// 显示提示
|
||||
notification.error({
|
||||
message: error.message
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 创建一个错误
|
||||
* @param {String} msg 错误信息
|
||||
*/
|
||||
export function errorCreate(msg) {
|
||||
const error = new Error(msg);
|
||||
errorLog(error);
|
||||
throw error;
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
import _ from "lodash-es";
|
||||
|
||||
function handleInputs(inputs) {
|
||||
if (inputs == null) {
|
||||
return;
|
||||
}
|
||||
_.forEach(inputs, (item, key) => {
|
||||
if (item.required === true) {
|
||||
if (item.component == null) {
|
||||
item.component = {};
|
||||
}
|
||||
let rules = item.component.rules;
|
||||
if (rules == null) {
|
||||
item.component.rules = rules = [];
|
||||
}
|
||||
if (rules.length > 0) {
|
||||
const hasRequired = rules.filter((rule) => {
|
||||
return rule.required === true;
|
||||
});
|
||||
if (hasRequired.length > 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
rules.push({ required: true, message: "该项必填" });
|
||||
delete item.required;
|
||||
}
|
||||
});
|
||||
}
|
||||
export default {
|
||||
handle(list) {
|
||||
_.forEach(list, (item) => {
|
||||
handleInputs(item.input);
|
||||
});
|
||||
}
|
||||
};
|
Before Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 7.4 KiB |
|
@ -1,17 +0,0 @@
|
|||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||
width="500" height="500" viewBox="0 0 500.000000 500.000000"
|
||||
>
|
||||
|
||||
|
||||
|
||||
<path d="M28.34 56.68h28.34V36.12H28.34a7.79 7.79 0 1 1 0-15.58h19.84v9.05h8.5V12H28.34a16.29 16.29 0 0 0 0 32.58h19.84v3.56H28.34a19.84 19.84 0 0 1 0-39.68h28.34V0H28.34a28.34 28.34 0 0 0 0 56.68z"
|
||||
fill="#2c3e50"
|
||||
transform="translate(124, 60) scale(4,4)"
|
||||
></path>
|
||||
<path d="M13.00-21.91L21.24-21.91L21.24-17.23L14.04-17.23Q10.39-17.23 9-15.62L9-15.62Q7.65-14.08 7.65-10.93L7.65-10.93Q7.65-7.42 9.86-5.80L9.86-5.80Q10.75-5.17 11.81-4.93Q12.87-4.68 14.76-4.68L14.76-4.68L21.24-4.68L21.24 0L13.00 0Q9.67 0 7.74-0.67Q5.80-1.35 4.32-3.01L4.32-3.01Q1.48-6.17 1.48-11.03L1.48-11.03Q1.48-16.88 4.86-19.75L4.86-19.75Q6.21-20.93 8.10-21.42Q9.99-21.91 13.00-21.91L13.00-21.91ZM31.05-13.32L43.74-13.32L43.74-8.64L31.05-8.64Q31.23-6.48 32.44-5.58Q33.66-4.68 36.41-4.68L36.41-4.68L43.74-4.68L43.74 0L35.73 0Q33.12 0 31.48-0.47Q29.83-0.94 28.39-2.02L28.39-2.02Q24.39-5.13 24.39-11.25L24.39-11.25Q24.39-15.21 26.50-18.18L26.50-18.18Q27.94-20.20 29.97-21.06Q31.99-21.91 35.28-21.91L35.28-21.91L43.74-21.91L43.74-17.23L35.73-17.23Q33.25-17.23 32.27-16.40Q31.27-15.57 31.05-13.32L31.05-13.32ZM48.64 0L48.64-21.91L57.55-21.91Q60.30-21.91 61.81-21.53Q63.31-21.15 64.31-20.25L64.31-20.25Q65.30-19.35 65.70-18Q66.10-16.65 66.10-14.13L66.10-14.13L66.10-12.01L60.30-12.01L60.30-13.18Q60.30-15.52 59.49-16.38Q58.68-17.23 56.38-17.23L56.38-17.23L54.67-17.23L54.67 0L48.64 0ZM67.50-21.91L71.33-21.91L71.33-30.02L77.36-30.02L77.36-21.91L82.94-21.91L82.94-17.23L77.36-17.23L77.36-9.27Q77.36-6.48 77.85-5.76L77.85-5.76Q78.61-4.68 80.55-4.68L80.55-4.68L82.94-4.68L82.94 0L78.57 0Q74.66 0 72.99-1.89Q71.33-3.78 71.33-8.23L71.33-8.23L71.33-17.23L67.50-17.23L67.50-21.91ZM96.08-21.91L101.75-21.91L101.75-30.02L107.73-30.02L107.73 0L97.38 0Q94.23 0 92.61-0.49L92.61-0.49Q88.78-1.71 86.90-5.26L86.90-5.26Q85.59-7.65 85.59-11.12L85.59-11.12Q85.59-16.74 89.37-19.84L89.37-19.84Q91.84-21.91 96.08-21.91L96.08-21.91ZM97.38-4.68L101.75-4.68L101.75-17.23L97.38-17.23Q94.50-17.23 93.02-15.30L93.02-15.30Q91.71-13.68 91.71-11.12L91.71-11.12Q91.71-7.38 93.87-5.76L93.87-5.76Q95.36-4.68 97.38-4.68L97.38-4.68Z"
|
||||
fill="#2c3e50"
|
||||
transform="translate(28, 430) scale(4,4)"
|
||||
|
||||
></path>
|
||||
|
||||
</svg>
|
Before Width: | Height: | Size: 2.3 KiB |
|
@ -1,295 +0,0 @@
|
|||
<template>
|
||||
<a-drawer
|
||||
title="授权管理"
|
||||
placement="right"
|
||||
:closable="true"
|
||||
width="500px"
|
||||
v-model:visible="visible"
|
||||
:destroyOnClose="true"
|
||||
@after-visible-change="onAfterVisibleChange"
|
||||
>
|
||||
<div class="d-container access-provider-manager">
|
||||
<a-button @click="add">
|
||||
添加授权
|
||||
</a-button>
|
||||
<a-list
|
||||
class="list"
|
||||
item-layout="horizontal"
|
||||
:data-source="getProviders()"
|
||||
>
|
||||
<template #renderItem="{ item ,index }">
|
||||
<a-list-item>
|
||||
<template #actions>
|
||||
<a-button type="primary" @click="openEdit(item,index)"><template #icon><EditOutlined /></template></a-button>
|
||||
<a-button type="danger" @click="remove(item,index)"><template #icon ><DeleteOutlined /></template></a-button>
|
||||
</template>
|
||||
|
||||
<a-radio :disabled="isDisabled(item)" :checked="item.key===selectedKey" @update:checked="selectedKey = item.key" >
|
||||
{{ item.name }} ({{item.type}})
|
||||
</a-radio>
|
||||
|
||||
</a-list-item>
|
||||
</template>
|
||||
</a-list>
|
||||
|
||||
<div>
|
||||
<a-button @click="onProviderSelectSubmit">确定</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</a-drawer>
|
||||
|
||||
<a-modal v-model:visible="editVisible" dialogClass="d-dialog" width="700px" title="编辑授权" @ok="onSubmit">
|
||||
|
||||
<a-alert v-if="currentProvider?.desc" :message="currentProvider.desc" type="success" />
|
||||
|
||||
<a-form ref="formRef" class="domain-form" :model="formData" labelWidth="150px" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<a-form-item label="类型" name="type" :rules="rules.type">
|
||||
<a-radio-group :disabled="editIndex!=null" v-model:value="formData.type" @change="onTypeChanged" >
|
||||
<a-radio-button v-for="(option) of providerDefineList" :disabled="isDisabled(option,'name')" :key="option.name" :value="option.name">
|
||||
{{option.label}}
|
||||
</a-radio-button>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
|
||||
<template v-if="formData.type && currentProvider">
|
||||
<a-form-item label="名称" name="name" :rules="rules.name">
|
||||
<a-input v-model:value="formData.name"/>
|
||||
</a-form-item>
|
||||
<a-form-item v-for="(item,key,index) in currentProvider.input"
|
||||
:key="index"
|
||||
v-bind="item.component||{}"
|
||||
:label="item.label || key"
|
||||
:name="key">
|
||||
<component-render v-model:value="formData[key]" v-bind="item.component || {}"></component-render>
|
||||
<template #extra >
|
||||
<div v-if="item.desc" class="helper">{{item.desc}}</div>
|
||||
</template>
|
||||
</a-form-item>
|
||||
</template>
|
||||
|
||||
</a-form>
|
||||
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref, reactive, nextTick, watch, inject } from 'vue'
|
||||
import _ from 'lodash-es'
|
||||
import providerApi from '../../api/api.access-providers'
|
||||
function useEdit (props, context, onEditSave) {
|
||||
const formData = reactive({
|
||||
key: '',
|
||||
name: '',
|
||||
type: undefined
|
||||
})
|
||||
|
||||
const rules = ref({
|
||||
type: [{
|
||||
type: 'string',
|
||||
required: true,
|
||||
message: '请选择类型'
|
||||
}],
|
||||
name: [{
|
||||
type: 'string',
|
||||
required: true,
|
||||
message: '请输入名称'
|
||||
}]
|
||||
})
|
||||
|
||||
const formRef = ref()
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
// const { resetFields, validate, validateInfos } = useForm(formData, rules)
|
||||
const onSubmit = async e => {
|
||||
e.preventDefault()
|
||||
const res = await formRef.value.validate()
|
||||
console.log('validation:', res)
|
||||
const newProvider = _.cloneDeep(formData)
|
||||
onEditSave(newProvider, editIndex.value)
|
||||
closeEdit()
|
||||
}
|
||||
|
||||
const editVisible = ref(false)
|
||||
const editIndex = ref(null)
|
||||
const openEdit = (item, index) => {
|
||||
if (item) {
|
||||
editIndex.value = index
|
||||
_.forEach(formData, (value, key) => {
|
||||
formData[key] = null
|
||||
})
|
||||
_.merge(formData, item)
|
||||
changeType(item.type)
|
||||
} else {
|
||||
editIndex.value = null
|
||||
formData.type = null
|
||||
}
|
||||
editVisible.value = true
|
||||
}
|
||||
const add = () => {
|
||||
openEdit()
|
||||
}
|
||||
const closeEdit = () => {
|
||||
editVisible.value = false
|
||||
}
|
||||
const providerDefineList = ref([])
|
||||
const onCreated = async () => {
|
||||
providerDefineList.value = await providerApi.list()
|
||||
}
|
||||
onCreated()
|
||||
const currentProvider = ref(null)
|
||||
const onTypeChanged = (e) => {
|
||||
const value = e.target.value
|
||||
changeType(value)
|
||||
// 遍历input 设置到form rules
|
||||
}
|
||||
const changeType = (type) => {
|
||||
if (providerDefineList.value == null) {
|
||||
return
|
||||
}
|
||||
for (const item of providerDefineList.value) {
|
||||
if (item.name === type) {
|
||||
currentProvider.value = item
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (editIndex.value == null) {
|
||||
// 添加时
|
||||
formData.key = currentProvider.value.name
|
||||
formData.name = currentProvider.value.label || currentProvider.value.name
|
||||
|
||||
// 设置默认值
|
||||
for (const key in currentProvider.value.input) {
|
||||
const input = currentProvider.value.input[key]
|
||||
if (input.default != null) {
|
||||
formData[key] = input.default
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const isDisabled = (item, keyName = 'type') => {
|
||||
if (!props.filter) {
|
||||
return false
|
||||
}
|
||||
return item[keyName
|
||||
] !== props.filter
|
||||
}
|
||||
return {
|
||||
labelCol: { span: 6 },
|
||||
wrapperCol: { span: 16 },
|
||||
formData,
|
||||
onSubmit,
|
||||
rules,
|
||||
editVisible,
|
||||
formRef,
|
||||
currentProvider,
|
||||
providerDefineList,
|
||||
editIndex,
|
||||
openEdit,
|
||||
onTypeChanged,
|
||||
add,
|
||||
isDisabled
|
||||
}
|
||||
}
|
||||
|
||||
let index = 0
|
||||
const keyPrefix = 'provider_'
|
||||
function generateNewKey (list) {
|
||||
index++
|
||||
let exists = false
|
||||
for (const item of list) {
|
||||
if (item.key === keyPrefix + index) {
|
||||
exists = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if (exists) {
|
||||
return generateNewKey(list)
|
||||
}
|
||||
return keyPrefix + index
|
||||
}
|
||||
export default {
|
||||
name: 'access-provider-manager',
|
||||
props: {
|
||||
value: {},
|
||||
filter: {}
|
||||
},
|
||||
emits: ['update:value'],
|
||||
setup (props, context) {
|
||||
const visible = ref(false)
|
||||
|
||||
const close = () => {
|
||||
visible.value = false
|
||||
}
|
||||
|
||||
const onAfterVisibleChange = () => {
|
||||
|
||||
}
|
||||
|
||||
const getProviders = inject('get:accessProviders')
|
||||
// const providerList = ref([])
|
||||
const selectedKey = ref(null)
|
||||
|
||||
watch(() => props.value, () => {
|
||||
selectedKey.value = props.value
|
||||
}, { immediate: true })
|
||||
|
||||
const onEditSave = (newProvider, editIndex) => {
|
||||
const providerList = getProviders()
|
||||
if (editIndex == null) {
|
||||
// add 生成一个key
|
||||
newProvider.key = generateNewKey(providerList)
|
||||
providerList.push(newProvider)
|
||||
} else {
|
||||
_.merge(providerList[editIndex], newProvider)
|
||||
}
|
||||
}
|
||||
|
||||
const editModule = useEdit(props, context, onEditSave)
|
||||
|
||||
const open = () => {
|
||||
visible.value = true
|
||||
const providerList = getProviders()
|
||||
if (providerList.length === 0) {
|
||||
nextTick(() => {
|
||||
editModule.add()
|
||||
})
|
||||
}
|
||||
}
|
||||
const remove = (item, index) => {
|
||||
const providerList = getProviders()
|
||||
providerList.splice(index, 1)
|
||||
}
|
||||
|
||||
const updateProviders = inject('update:accessProviders')
|
||||
|
||||
// watch(() => providers, () => {
|
||||
// providerList.value = _.cloneDeep(props.providers || [])
|
||||
// }, { immediate: true })
|
||||
|
||||
const onProviderSelectSubmit = () => {
|
||||
const providerList = getProviders()
|
||||
updateProviders(providerList)
|
||||
context.emit('update:value', selectedKey.value)
|
||||
close()
|
||||
}
|
||||
return {
|
||||
visible,
|
||||
open,
|
||||
close,
|
||||
onAfterVisibleChange,
|
||||
remove,
|
||||
selectedKey,
|
||||
onProviderSelectSubmit,
|
||||
getProviders,
|
||||
...editModule
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
.access-provider-manager{
|
||||
padding:10px;
|
||||
}
|
||||
</style>
|
|
@ -1,87 +0,0 @@
|
|||
<template>
|
||||
<div>
|
||||
<div class="access-provider-selector">
|
||||
<a-select
|
||||
:value="value"
|
||||
@update:value="valueUpdate"
|
||||
placeholder="没有可选时请点右边按钮添加"
|
||||
>
|
||||
<a-select-option v-for="item of getProviders()" :key="item.key" :value="item.key" :disabled="isDisabled(item)">
|
||||
{{ item.name }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
<a-button class="suffix" @click="providerManagerOpen">
|
||||
添加授权
|
||||
</a-button>
|
||||
</div>
|
||||
<access-provider-manager ref="providerManagerRef"
|
||||
:value="value"
|
||||
:filter="filter"
|
||||
@update:value="valueUpdate"
|
||||
></access-provider-manager>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { ref, inject } from 'vue'
|
||||
import AccessProviderManager from './access-provider-manager.vue'
|
||||
|
||||
export default {
|
||||
name: 'access-provider-selector',
|
||||
components: { AccessProviderManager },
|
||||
emits: ['update:providers', 'update:value'],
|
||||
// 属性定义
|
||||
props: {
|
||||
value: {
|
||||
type: String
|
||||
},
|
||||
filter: {}
|
||||
},
|
||||
setup (props, context) {
|
||||
const providerManagerRef = ref(null)
|
||||
const providerManagerOpen = () => {
|
||||
console.log('providerManagerRef', providerManagerRef)
|
||||
if (providerManagerRef.value) {
|
||||
providerManagerRef.value.open()
|
||||
}
|
||||
}
|
||||
const providersUpdate = (val) => {
|
||||
console.log('accessUpdate', val)
|
||||
context.emit('update:providers', val)
|
||||
}
|
||||
const valueUpdate = (val) => {
|
||||
context.emit('update:value', val)
|
||||
}
|
||||
|
||||
const isDisabled = (item) => {
|
||||
if (!props.filter) {
|
||||
return false
|
||||
}
|
||||
return item.type !== props.filter
|
||||
}
|
||||
|
||||
const getProviders = inject('get:accessProviders')
|
||||
|
||||
return {
|
||||
providersUpdate,
|
||||
valueUpdate,
|
||||
providerManagerOpen,
|
||||
providerManagerRef,
|
||||
isDisabled,
|
||||
getProviders
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="less">
|
||||
.access-provider-selector{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
.ant-select{
|
||||
flex:1;
|
||||
}
|
||||
.suffix{
|
||||
flex-shrink: 0;
|
||||
margin-left:5px;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,33 +0,0 @@
|
|||
<script>
|
||||
import { h, resolveComponent } from 'vue'
|
||||
import _ from 'lodash-es'
|
||||
export default {
|
||||
name: 'component-render',
|
||||
props: {
|
||||
name: {
|
||||
type: String,
|
||||
default: 'a-input'
|
||||
},
|
||||
children: {
|
||||
type: Array
|
||||
},
|
||||
on: {
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
setup (props, context) {
|
||||
const attrs = {
|
||||
...context.$attrs
|
||||
}
|
||||
_.forEach(props.on, (value, key) => {
|
||||
attrs[key] = value
|
||||
if (typeof value === 'string') {
|
||||
// eslint-disable-next-line no-eval
|
||||
attrs[key] = eval(value)
|
||||
}
|
||||
})
|
||||
const comp = resolveComponent(props.name)
|
||||
return () => h(comp, context.$attrs, props.children)
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -1,56 +0,0 @@
|
|||
<template>
|
||||
<div class="d-container">
|
||||
<div class="box">
|
||||
<div class="inner">
|
||||
<div class="header">
|
||||
<slot name="header"></slot>
|
||||
</div>
|
||||
<div class="body">
|
||||
<slot></slot>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<slot name="footer"></slot>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'd-container'
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
.d-container{
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
.box {
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
.inner{
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.header{
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.body{
|
||||
overflow-y: auto;
|
||||
flex:1
|
||||
}
|
||||
.footer{
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
|
@ -1,16 +0,0 @@
|
|||
import DContainer from './d-container.vue'
|
||||
import ComponentRender from './component-render.vue'
|
||||
import AccessProviderSelector from './access-provider-selector/access-provider-selector.vue'
|
||||
|
||||
const list = [
|
||||
DContainer,
|
||||
ComponentRender,
|
||||
AccessProviderSelector
|
||||
]
|
||||
export default {
|
||||
install (app) {
|
||||
for (const item of list) {
|
||||
app.component(item.name, item)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
import { createI18n } from 'vue-i18n'
|
||||
import zh from './locales/zh.json'
|
||||
import en from './locales/en.json'
|
||||
export const i18n = createI18n({
|
||||
// something vue-i18n options here ...
|
||||
locale: 'zh', // set current locale
|
||||
messages: {
|
||||
en,
|
||||
zh
|
||||
}
|
||||
})
|
|
@ -1,26 +0,0 @@
|
|||
import _ from 'lodash'
|
||||
import {
|
||||
PlusCircleOutlined,
|
||||
PlusOutlined,
|
||||
CheckOutlined, EditOutlined,
|
||||
ArrowRightOutlined,
|
||||
NodeIndexOutlined,
|
||||
ThunderboltOutlined,
|
||||
DeleteOutlined
|
||||
} from '@ant-design/icons-vue'
|
||||
|
||||
const icons = {
|
||||
PlusCircleOutlined,
|
||||
PlusOutlined,
|
||||
CheckOutlined,
|
||||
EditOutlined,
|
||||
ArrowRightOutlined,
|
||||
NodeIndexOutlined,
|
||||
ThunderboltOutlined,
|
||||
DeleteOutlined
|
||||
}
|
||||
export default function (app) {
|
||||
_.forEach(icons, (item, key) => {
|
||||
app.component(key, item)
|
||||
})
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
{
|
||||
|
||||
}
|