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": {
|
"devDependencies": {
|
||||||
"@types/lodash": "^4.14.186",
|
"@types/lodash": "^4.14.186",
|
||||||
"@fast-crud/fast-crud": "^1.5.0",
|
|
||||||
"vue-tsc": "^0.38.9",
|
"vue-tsc": "^0.38.9",
|
||||||
"@alicloud/cs20151215": "^3.0.3",
|
"@alicloud/cs20151215": "^3.0.3",
|
||||||
"@alicloud/openapi-client": "^0.4.0",
|
"@alicloud/openapi-client": "^0.4.0",
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
import { Registrable } from "../registry";
|
import { Registrable } from "../registry";
|
||||||
import { FormItemProps } from "@fast-crud/fast-crud";
|
|
||||||
import { accessRegistry } from "./registry";
|
import { accessRegistry } from "./registry";
|
||||||
|
import { FormItemProps } from "../d.ts";
|
||||||
|
|
||||||
|
export type AccessInput = FormItemProps & {
|
||||||
|
title: string;
|
||||||
|
required?: boolean;
|
||||||
|
};
|
||||||
export type AccessDefine = Registrable & {
|
export type AccessDefine = Registrable & {
|
||||||
input: {
|
input: {
|
||||||
[key: string]: FormItemProps;
|
[key: string]: AccessInput;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
export function IsAccess(define: AccessDefine) {
|
export function IsAccess(define: AccessDefine) {
|
||||||
|
|
|
@ -7,11 +7,18 @@ import { AbstractAccess } from "../abstract-access";
|
||||||
desc: "",
|
desc: "",
|
||||||
input: {
|
input: {
|
||||||
accessKeyId: {
|
accessKeyId: {
|
||||||
|
title: "accessKeyId",
|
||||||
component: {
|
component: {
|
||||||
placeholder: "accessKeyId",
|
placeholder: "accessKeyId",
|
||||||
},
|
},
|
||||||
//required: true,
|
required: true,
|
||||||
//rules: [{ required: true, message: "必填项" }],
|
},
|
||||||
|
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 "./pipeline";
|
||||||
|
export * from "./fast-crud";
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { FormItemProps } from "@fast-crud/fast-crud";
|
|
||||||
import { Registrable } from "../registry";
|
import { Registrable } from "../registry";
|
||||||
import { pluginRegistry } from "./registry";
|
import { pluginRegistry } from "./registry";
|
||||||
|
import { FormItemProps } from "../d.ts";
|
||||||
export type TaskInput = {
|
export type TaskInput = {
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,7 +5,7 @@ import dayjs from "dayjs";
|
||||||
import { dnsProviderRegistry } from "../../../dns-provider";
|
import { dnsProviderRegistry } from "../../../dns-provider";
|
||||||
import { AbstractDnsProvider } from "../../../dns-provider/abstract-dns-provider";
|
import { AbstractDnsProvider } from "../../../dns-provider/abstract-dns-provider";
|
||||||
import { AcmeService } from "./acme";
|
import { AcmeService } from "./acme";
|
||||||
|
import _ from "lodash";
|
||||||
export type CertInfo = {
|
export type CertInfo = {
|
||||||
crt: string;
|
crt: string;
|
||||||
key: string;
|
key: string;
|
||||||
|
@ -15,6 +15,7 @@ export type CertInfo = {
|
||||||
return {
|
return {
|
||||||
name: "CertApply",
|
name: "CertApply",
|
||||||
title: "证书申请",
|
title: "证书申请",
|
||||||
|
desc: "免费通配符域名证书申请,支持多个域名打到同一个证书上",
|
||||||
input: {
|
input: {
|
||||||
domains: {
|
domains: {
|
||||||
title: "域名",
|
title: "域名",
|
||||||
|
@ -22,12 +23,17 @@ export type CertInfo = {
|
||||||
name: "a-select",
|
name: "a-select",
|
||||||
vModel: "value",
|
vModel: "value",
|
||||||
mode: "tags",
|
mode: "tags",
|
||||||
|
open: false,
|
||||||
},
|
},
|
||||||
required: true,
|
required: true,
|
||||||
col: {
|
col: {
|
||||||
span: 24,
|
span: 24,
|
||||||
},
|
},
|
||||||
helper: "请输入域名",
|
helper:
|
||||||
|
"支持通配符域名,例如: *.foo.com 、 *.test.handsfree.work\n" +
|
||||||
|
"支持多个域名、多个子域名、多个通配符域名打到一个证书上(域名必须是在同一个DNS提供商解析)\n" +
|
||||||
|
"多级子域名要分成多个域名输入(*.foo.com的证书不能用于xxx.yyy.foo.com)\n" +
|
||||||
|
"输入一个回车之后,再输入下一个",
|
||||||
},
|
},
|
||||||
email: {
|
email: {
|
||||||
title: "邮箱",
|
title: "邮箱",
|
||||||
|
@ -138,7 +144,17 @@ export class CertApplyPlugin extends AbstractPlugin implements TaskPlugin {
|
||||||
const domains = input["domains"];
|
const domains = input["domains"];
|
||||||
const dnsProviderType = input["dnsProviderType"];
|
const dnsProviderType = input["dnsProviderType"];
|
||||||
const dnsProviderAccessId = input["dnsProviderAccess"];
|
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);
|
this.logger.info("开始申请证书,", email, domains);
|
||||||
|
|
||||||
const dnsProviderClass = dnsProviderRegistry.get(dnsProviderType);
|
const dnsProviderClass = dnsProviderRegistry.get(dnsProviderType);
|
||||||
|
|
|
@ -59,11 +59,21 @@ export class Registry<T extends typeof AbstractRegistrable> {
|
||||||
getDefineList() {
|
getDefineList() {
|
||||||
const list = [];
|
const list = [];
|
||||||
for (const key in this.storage) {
|
for (const key in this.storage) {
|
||||||
const PluginClass = this.storage[key];
|
const define = this.getDefine(key);
|
||||||
// @ts-ignore
|
if (define) {
|
||||||
const plugin = new PluginClass();
|
list.push({ ...define, key });
|
||||||
list.push({ ...plugin.define, key });
|
}
|
||||||
}
|
}
|
||||||
return list;
|
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,
|
version: 1,
|
||||||
id: generateId(),
|
id: generateId(),
|
||||||
title: "测试管道",
|
title: "测试管道",
|
||||||
|
userId: 1,
|
||||||
triggers: [],
|
triggers: [],
|
||||||
stages: [
|
stages: [
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,5 +7,18 @@ export default defineConfig({
|
||||||
entry: "src/index.ts",
|
entry: "src/index.ts",
|
||||||
name: "pipeline",
|
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 @@
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|