@ -0,0 +1,147 @@ |
|||||
|
# ---> Go |
||||
|
# Binaries for programs and plugins |
||||
|
*.exe |
||||
|
*.exe~ |
||||
|
*.dll |
||||
|
*.so |
||||
|
*.dylib |
||||
|
|
||||
|
# Test binary, built with `go test -c` |
||||
|
*.test |
||||
|
|
||||
|
# Output of the go coverage tool, specifically when used with LiteIDE |
||||
|
*.out |
||||
|
|
||||
|
# Dependency directories (remove the comment below to include it) |
||||
|
# vendor/ |
||||
|
|
||||
|
# ---> Node |
||||
|
# Logs |
||||
|
logs |
||||
|
*.log |
||||
|
npm-debug.log* |
||||
|
yarn-debug.log* |
||||
|
yarn-error.log* |
||||
|
lerna-debug.log* |
||||
|
.pnpm-debug.log* |
||||
|
|
||||
|
# Diagnostic reports (https://nodejs.org/api/report.html) |
||||
|
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json |
||||
|
|
||||
|
# Runtime data |
||||
|
pids |
||||
|
*.pid |
||||
|
*.seed |
||||
|
*.pid.lock |
||||
|
|
||||
|
# Directory for instrumented libs generated by jscoverage/JSCover |
||||
|
lib-cov |
||||
|
|
||||
|
# Coverage directory used by tools like istanbul |
||||
|
coverage |
||||
|
*.lcov |
||||
|
|
||||
|
# nyc test coverage |
||||
|
.nyc_output |
||||
|
|
||||
|
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) |
||||
|
.grunt |
||||
|
|
||||
|
# Bower dependency directory (https://bower.io/) |
||||
|
bower_components |
||||
|
|
||||
|
# node-waf configuration |
||||
|
.lock-wscript |
||||
|
|
||||
|
# Compiled binary addons (https://nodejs.org/api/addons.html) |
||||
|
build/Release |
||||
|
|
||||
|
# Dependency directories |
||||
|
node_modules |
||||
|
jspm_packages/ |
||||
|
|
||||
|
# Snowpack dependency directory (https://snowpack.dev/) |
||||
|
web_modules/ |
||||
|
|
||||
|
# TypeScript cache |
||||
|
*.tsbuildinfo |
||||
|
|
||||
|
# Optional npm cache directory |
||||
|
.npm |
||||
|
|
||||
|
# Optional eslint cache |
||||
|
.eslintcache |
||||
|
|
||||
|
# Microbundle cache |
||||
|
.rpt2_cache/ |
||||
|
.rts2_cache_cjs/ |
||||
|
.rts2_cache_es/ |
||||
|
.rts2_cache_umd/ |
||||
|
|
||||
|
# Optional REPL history |
||||
|
.node_repl_history |
||||
|
|
||||
|
# Output of 'npm pack' |
||||
|
*.tgz |
||||
|
|
||||
|
# Yarn Integrity file |
||||
|
.yarn-integrity |
||||
|
|
||||
|
# dotenv environment variables file |
||||
|
.env |
||||
|
.env.test |
||||
|
.env.production |
||||
|
|
||||
|
# parcel-bundler cache (https://parceljs.org/) |
||||
|
.cache |
||||
|
.parcel-cache |
||||
|
|
||||
|
# Next.js build output |
||||
|
.next |
||||
|
out |
||||
|
|
||||
|
# Nuxt.js build / generate output |
||||
|
.nuxt |
||||
|
dist |
||||
|
|
||||
|
# Gatsby files |
||||
|
.cache/ |
||||
|
# Comment in the public line in if your project uses Gatsby and not Next.js |
||||
|
# https://nextjs.org/blog/next-9-1#public-directory-support |
||||
|
# public |
||||
|
|
||||
|
# vuepress build output |
||||
|
.vuepress/dist |
||||
|
|
||||
|
# Serverless directories |
||||
|
.serverless/ |
||||
|
|
||||
|
# FuseBox cache |
||||
|
.fusebox/ |
||||
|
|
||||
|
# DynamoDB Local files |
||||
|
.dynamodb/ |
||||
|
|
||||
|
# TernJS port file |
||||
|
.tern-port |
||||
|
|
||||
|
# Stores VSCode versions used for testing VSCode extensions |
||||
|
.vscode-test |
||||
|
|
||||
|
# yarn v2 |
||||
|
.yarn/cache |
||||
|
.yarn/unplugged |
||||
|
.yarn/build-state.yml |
||||
|
.yarn/install-state.gz |
||||
|
.pnp.* |
||||
|
|
||||
|
*yarn.lock |
||||
|
*package-lock.json |
||||
|
*log/ |
||||
|
*downloadFiles/ |
||||
|
web/client/assets/color.less |
||||
|
package-lock.json |
||||
|
development.text |
||||
|
|
||||
|
web/node_modules |
||||
|
web/log |
@ -0,0 +1,49 @@ |
|||||
|
{ |
||||
|
// 使用 IntelliSense 了解相关属性。 |
||||
|
// 悬停以查看现有属性的描述。 |
||||
|
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 |
||||
|
"version": "0.2.0", |
||||
|
"configurations": [ |
||||
|
{ |
||||
|
"type": "node", |
||||
|
"request": "launch", |
||||
|
"name": "启动 API", |
||||
|
"program": "${workspaceRoot}/server.js", |
||||
|
"env": { |
||||
|
"NODE_ENV": "development" |
||||
|
}, |
||||
|
"args": [ |
||||
|
"-p 4900", |
||||
|
// 研发 |
||||
|
"-g postgres://postgres:123456@10.8.30.166:5432/XunJian", |
||||
|
// 测试 |
||||
|
// "--apiEmisUrl http://10.8.30.161:1111", |
||||
|
"--qnak XuDgkao6cL0HidoMAPnA5OB10Mc_Ew08mpIfRJK5", |
||||
|
"--qnsk yewcieZLzKZuDfig0wLZ9if9jKp2P_1jd3CMJPSa", |
||||
|
"--qnbkt dev-hr", |
||||
|
// "--qndmn http://resources.anxinyun.cn", |
||||
|
"--qndmn http://rjkwed13l.hn-bkt.clouddn.com", |
||||
|
"--aliOssAccessKey LTAI5tNDfn7UhStYQcn3JBtw", |
||||
|
"--aliOssSecretKey rnoXtDWQA1djJ5Xqcdn1OSEol0lVyv", |
||||
|
"--aliOssBucket test-c371", |
||||
|
"--aliOssRegion oss-cn-hangzhou", |
||||
|
] |
||||
|
}, |
||||
|
{ |
||||
|
"type": "node", |
||||
|
"request": "launch", |
||||
|
"name": "run mocha", |
||||
|
"program": "${workspaceRoot}/node_modules/mocha/bin/_mocha", |
||||
|
"stopOnEntry": false, |
||||
|
"args": [ |
||||
|
"app/test/*.test.js", |
||||
|
"--no-timeouts" |
||||
|
], |
||||
|
"cwd": "${workspaceRoot}", |
||||
|
"runtimeExecutable": null, |
||||
|
"env": { |
||||
|
"NODE_ENV": "development" |
||||
|
} |
||||
|
} |
||||
|
] |
||||
|
} |
@ -0,0 +1,36 @@ |
|||||
|
FROM registry.cn-hangzhou.aliyuncs.com/fs-devops/node:12-dev as builder |
||||
|
|
||||
|
COPY . /var/app |
||||
|
|
||||
|
WORKDIR /var/app |
||||
|
|
||||
|
EXPOSE 8080 |
||||
|
|
||||
|
RUN npm config set registry=http://10.8.30.22:7000 |
||||
|
RUN echo "{\"time\":\"$BUILD_TIMESTAMP\",\"build\": \"$BUILD_NUMBER\",\"revision\": \"$SVN_REVISION_1\",\"URL\":\"$SVN_URL_1\"}" > version.json |
||||
|
RUN npm cache clean -f |
||||
|
RUN rm -rf package-lock.json |
||||
|
RUN npm install --registry http://10.8.30.22:7000 |
||||
|
|
||||
|
FROM registry.cn-hangzhou.aliyuncs.com/fs-devops/node:12 |
||||
|
|
||||
|
COPY --from=builder --chown=node /var/app /home/node/app |
||||
|
|
||||
|
WORKDIR /home/node/app |
||||
|
|
||||
|
CMD ["node", "server.js"] |
||||
|
|
||||
|
|
||||
|
# 旧版本构建方式 |
||||
|
|
||||
|
# FROM repository.anxinyun.cn/base-images/nodejs12:20.10.12.2 |
||||
|
|
||||
|
# COPY . /var/app |
||||
|
|
||||
|
# WORKDIR /var/app |
||||
|
|
||||
|
# EXPOSE 8080 |
||||
|
|
||||
|
# CMD ["-u", "http://localhost:8088"] |
||||
|
|
||||
|
# ENTRYPOINT [ "node", "server.js" ] |
@ -0,0 +1,3 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
module.exports = require('./lib'); |
@ -0,0 +1,162 @@ |
|||||
|
'use strict'; |
||||
|
const Hex = require('crypto-js/enc-hex'); |
||||
|
const SHA1 = require('crypto-js/sha1'); |
||||
|
const MD5 = require('crypto-js/md5'); |
||||
|
const moment = require('moment'); |
||||
|
const uuid = require('uuid'); |
||||
|
|
||||
|
async function login(ctx, next) { |
||||
|
try { |
||||
|
const transaction = await ctx.fs.dc.orm.transaction(); |
||||
|
|
||||
|
const models = ctx.fs.dc.models; |
||||
|
const params = ctx.request.body; |
||||
|
let password = Hex.stringify(MD5(params.password)); |
||||
|
const userRes = await models.User.findOne({ |
||||
|
where: { |
||||
|
username: params.username, |
||||
|
password: password, |
||||
|
delete: false, |
||||
|
enable: true |
||||
|
}, |
||||
|
attributes: { exclude: ['password'] }, |
||||
|
include: [{ |
||||
|
attributes: ["resourceId"], |
||||
|
model: models.UserResource |
||||
|
}] |
||||
|
}); |
||||
|
|
||||
|
|
||||
|
if (!userRes) { |
||||
|
ctx.status = 400; |
||||
|
ctx.body = { |
||||
|
"message": "账号或密码错误" |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (userRes) |
||||
|
if (userRes && !userRes.enable) { |
||||
|
ctx.status = 400; |
||||
|
ctx.body = { message: "该用户已被禁用" } |
||||
|
} else { |
||||
|
const token = uuid.v4(); |
||||
|
let deptInfo = null; |
||||
|
if (userRes) { |
||||
|
const { departmentId } = userRes.dataValues; |
||||
|
deptInfo = await models.Department.findOne({ |
||||
|
where: { |
||||
|
id: departmentId |
||||
|
} |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
if (!userRes) { |
||||
|
ctx.status = 400; |
||||
|
ctx.body = { message: "暂无登录权限,请联系管理员" } |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
let userData = userRes.dataValues; |
||||
|
let userRslt = Object.assign(userData, { |
||||
|
authorized: true, |
||||
|
token: token, |
||||
|
userResources: userRes ? userRes.userResources.map(r => r.resourceId) : [], |
||||
|
type: deptInfo ? deptInfo.type : '', |
||||
|
deptName: deptInfo ? deptInfo.name : '', |
||||
|
}); |
||||
|
await models.UserToken.create({ |
||||
|
token: token, |
||||
|
userInfo: userRslt, |
||||
|
expired: moment().add(30, 'days').format() |
||||
|
}); |
||||
|
|
||||
|
ctx.status = 200; |
||||
|
ctx.body = userRslt; |
||||
|
} |
||||
|
await transaction.commit(); |
||||
|
} catch (error) { |
||||
|
await transaction.rollback(); |
||||
|
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |
||||
|
ctx.status = 400; |
||||
|
ctx.body = { |
||||
|
"message": "登录失败" |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
async function varfiyCode(ctx) { |
||||
|
try { |
||||
|
const { models } = ctx.fs.dc; |
||||
|
const { pushBySms, pushByEmail } = ctx.app.fs.utils |
||||
|
const { phone, sig, r } = ctx.request.body |
||||
|
|
||||
|
// 伪造的请求可能由相同的sig参数组成
|
||||
|
const checkSigUsed = await models.PhoneValidateCode.findOne({ |
||||
|
where: { sig: sig } |
||||
|
}); |
||||
|
if (checkSigUsed) { |
||||
|
throw '参数错误!' |
||||
|
} |
||||
|
|
||||
|
// 验证sig正确性
|
||||
|
const checkSig = Hex.stringify(SHA1(phone + r)); |
||||
|
if (!r || !sig || sig != checkSig) { |
||||
|
throw '参数错误!' |
||||
|
} |
||||
|
|
||||
|
let varifyCode = '' |
||||
|
for (let i = 0; i < 6; i++) { |
||||
|
varifyCode += Math.floor(Math.random() * 10) |
||||
|
} |
||||
|
|
||||
|
// await pushBySms({
|
||||
|
// phone: phone,
|
||||
|
// templateCode: 'SMS_248250074',
|
||||
|
// templateParam: {
|
||||
|
// code: varifyCode
|
||||
|
// },
|
||||
|
// })
|
||||
|
|
||||
|
await models.PhoneValidateCode.create({ |
||||
|
phone: phone, |
||||
|
code: varifyCode, |
||||
|
sig: sig, |
||||
|
expired: moment().add(10, 'minutes').format('YYYY-MM-DD HH:mm:ss') |
||||
|
}) |
||||
|
|
||||
|
ctx.status = 204; |
||||
|
} catch (error) { |
||||
|
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |
||||
|
ctx.status = 400; |
||||
|
ctx.body = { |
||||
|
message: typeof error == 'string' ? error : '获取验证码失败' |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
async function logout(ctx) { |
||||
|
try { |
||||
|
const models = ctx.fs.dc.models; |
||||
|
const params = ctx.request.body; |
||||
|
|
||||
|
await models.UserToken.destroy({ |
||||
|
where: { |
||||
|
token: params.token, |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
ctx.status = 204; |
||||
|
} catch (error) { |
||||
|
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |
||||
|
ctx.status = 400; |
||||
|
ctx.body = { |
||||
|
message: typeof error == 'string' ? error : undefined |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
module.exports = { |
||||
|
login, |
||||
|
varfiyCode, |
||||
|
logout, |
||||
|
}; |
@ -0,0 +1,87 @@ |
|||||
|
async function getResource(ctx, next) { |
||||
|
try { |
||||
|
const models = ctx.fs.dc.models; |
||||
|
|
||||
|
const res = await models.Resource.findAll({ |
||||
|
where: { parentResource: null }, |
||||
|
include: [{ |
||||
|
model: models.Resource, |
||||
|
}] |
||||
|
}) |
||||
|
|
||||
|
ctx.body = res; |
||||
|
ctx.status = 200; |
||||
|
|
||||
|
} catch (error) { |
||||
|
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |
||||
|
ctx.status = 400; |
||||
|
ctx.body = { |
||||
|
"message": "查询所有权限数据失败" |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
async function getUserResource(ctx, next) { |
||||
|
try { |
||||
|
const models = ctx.fs.dc.models; |
||||
|
const { userId } = ctx.query; |
||||
|
|
||||
|
const res = await models.UserResource.findAll({ |
||||
|
where: { userId: userId }, |
||||
|
include: [{ |
||||
|
model: models.Resource, |
||||
|
}] |
||||
|
}) |
||||
|
|
||||
|
ctx.body = res; |
||||
|
ctx.status = 200; |
||||
|
|
||||
|
} catch (error) { |
||||
|
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |
||||
|
ctx.status = 400; |
||||
|
ctx.body = { |
||||
|
"message": "查询用户权限数据失败" |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
async function updateUserRes(ctx, next) { |
||||
|
const transaction = await ctx.fs.dc.orm.transaction(); |
||||
|
try { |
||||
|
const models = ctx.fs.dc.models; |
||||
|
const { userId, resCode } = ctx.request.body; |
||||
|
|
||||
|
const res = await models.UserResource.findAll({ |
||||
|
attributes: ["resourceId"], |
||||
|
raw: true, |
||||
|
where: { userId: userId } |
||||
|
}) |
||||
|
|
||||
|
const addRes = resCode.filter(r => !res.some(rr => rr.resourceId == r)).map(r => { return { userId: userId, resourceId: r } }); |
||||
|
const delRes = res.filter(r => !resCode.includes(r.resourceId)).map(r => r.resourceId); |
||||
|
addRes.length && await models.UserResource.bulkCreate(addRes, { transaction: transaction }); |
||||
|
delRes.length && await models.UserResource.destroy({ |
||||
|
where: { |
||||
|
resourceId: { $in: delRes }, |
||||
|
userId: userId |
||||
|
}, |
||||
|
transaction: transaction |
||||
|
}) |
||||
|
|
||||
|
ctx.status = 204; |
||||
|
await transaction.commit(); |
||||
|
|
||||
|
} catch (error) { |
||||
|
await transaction.rollback(); |
||||
|
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |
||||
|
ctx.status = 400; |
||||
|
ctx.body = { |
||||
|
"message": "更新用户权限数据失败" |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
module.exports = { |
||||
|
getResource, |
||||
|
getUserResource, |
||||
|
updateUserRes |
||||
|
}; |
@ -0,0 +1,389 @@ |
|||||
|
'use strict'; |
||||
|
const Hex = require('crypto-js/enc-hex'); |
||||
|
const MD5 = require('crypto-js/md5'); |
||||
|
|
||||
|
// async function getDepMessage (ctx, next) {
|
||||
|
// try {
|
||||
|
// const { fs: { api: { userInfo } } } = ctx
|
||||
|
// const models = ctx.fs.dc.models;
|
||||
|
|
||||
|
// let deptWhere = {}
|
||||
|
// if (userInfo.username !== 'SuperAdmin') {
|
||||
|
// deptWhere.id = userInfo.departmentId
|
||||
|
// }
|
||||
|
// let depType1 = await models.Department.findAll({
|
||||
|
// order: [['id', 'asc']],
|
||||
|
// // include: [{
|
||||
|
// // model: models.User,
|
||||
|
// // required: false,
|
||||
|
// // where: { delete: false },
|
||||
|
// // attributes: { exclude: ['password'] },
|
||||
|
// // }],
|
||||
|
// where: deptWhere,
|
||||
|
// })
|
||||
|
|
||||
|
// let depRslt = []
|
||||
|
// const getDep = async (d) => {
|
||||
|
// let subordinate = []
|
||||
|
// let depRes = await models.Department.findAll({
|
||||
|
// order: [['id', 'asc']],
|
||||
|
// // include: [{
|
||||
|
// // model: models.User,
|
||||
|
// // required: false,
|
||||
|
// // where: { delete: false },
|
||||
|
// // attributes: { exclude: ['password'] },
|
||||
|
// // }],
|
||||
|
// where: {
|
||||
|
// dependence: d.id
|
||||
|
// },
|
||||
|
// })
|
||||
|
// if (depRes.length)
|
||||
|
// for (let d of depRes) {
|
||||
|
// let dep = d.dataValues
|
||||
|
// dep.subordinate = await getDep(d.dataValues)
|
||||
|
// subordinate.push(dep)
|
||||
|
// }
|
||||
|
// return subordinate
|
||||
|
// }
|
||||
|
// for (let d of depType1) {
|
||||
|
// let dep_1 = d.dataValues
|
||||
|
// dep_1.subordinate = await getDep(d.dataValues)
|
||||
|
// depRslt.push(dep_1)
|
||||
|
// }
|
||||
|
|
||||
|
// ctx.status = 200;
|
||||
|
// ctx.body = depRslt
|
||||
|
// } catch (error) {
|
||||
|
// ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
|
||||
|
// ctx.status = 400;
|
||||
|
// ctx.body = {
|
||||
|
// "message": "获取部门信息失败"
|
||||
|
// }
|
||||
|
// }
|
||||
|
// }
|
||||
|
|
||||
|
async function getDepMessage(ctx, next) { |
||||
|
let error = { name: 'FindError', message: '获取部门列表失败' }; |
||||
|
let rslt = []; |
||||
|
try { |
||||
|
const models = ctx.fs.dc.models; |
||||
|
let list = await models.Department.findAll({}); |
||||
|
|
||||
|
let deptMap = [] |
||||
|
list.filter(l => !l.dependence).map(ld => {//一级
|
||||
|
deptMap.push({ |
||||
|
id: ld.id, |
||||
|
name: ld.name, |
||||
|
dependence: ld.dependence, |
||||
|
subordinate: [] |
||||
|
}) |
||||
|
}) |
||||
|
|
||||
|
list.filter(l => l.dependence).map(ld => {//二级
|
||||
|
let parent = deptMap.find(dm => dm.id == ld.dependence); |
||||
|
if (parent) { |
||||
|
parent.subordinate.push({ |
||||
|
id: ld.id, |
||||
|
name: ld.name, |
||||
|
dependence: ld.dependence, |
||||
|
subordinate: [] |
||||
|
}) |
||||
|
} |
||||
|
}) |
||||
|
rslt = deptMap; |
||||
|
|
||||
|
error = null; |
||||
|
} catch (err) { |
||||
|
ctx.fs.logger.error(`path: ${ctx.path}, error: ${err}`); |
||||
|
} |
||||
|
if (error) { |
||||
|
ctx.status = 400; |
||||
|
ctx.body = error; |
||||
|
} else { |
||||
|
ctx.status = 200; |
||||
|
ctx.body = rslt; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
async function createDept(ctx, next) { |
||||
|
const models = ctx.fs.dc.models; |
||||
|
try { |
||||
|
let rslt = ctx.request.body; |
||||
|
await models.Department.create(Object.assign({}, rslt, { read: 1 })) |
||||
|
ctx.status = 204; |
||||
|
ctx.body = { message: '新建部门成功' } |
||||
|
} catch (error) { |
||||
|
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |
||||
|
ctx.status = 400; |
||||
|
ctx.body = { message: '新建部门失败' } |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
async function updateDept(ctx, next) { |
||||
|
try { |
||||
|
const models = ctx.fs.dc.models; |
||||
|
const { id } = ctx.params; |
||||
|
const body = ctx.request.body; |
||||
|
await models.Department.update( |
||||
|
body, |
||||
|
{ where: { id: id } } |
||||
|
) |
||||
|
ctx.status = 204; |
||||
|
ctx.body = { message: '修改部门成功' } |
||||
|
} catch (error) { |
||||
|
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |
||||
|
ctx.status = 400; |
||||
|
ctx.body = { message: '修改部门失败' } |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
async function delDept(ctx, next) { |
||||
|
let errMsg = "删除部门失败"; |
||||
|
try { |
||||
|
const models = ctx.fs.dc.models; |
||||
|
const { id } = ctx.params; |
||||
|
let list = await models.Department.findAll({}); |
||||
|
let deptIds = list.map(l => l.id); |
||||
|
const allUsers = await models.User.findAll({ |
||||
|
where: { |
||||
|
departmentId: { $in: deptIds }, |
||||
|
delete: false |
||||
|
} |
||||
|
}) |
||||
|
const childrenDept = await models.Department.findAll({ where: { dependence: id } }) |
||||
|
const childrenUser = allUsers.filter(au => au.departmentId == id); |
||||
|
if (childrenUser.length || childrenDept.length) { |
||||
|
errMsg = '请先删除部门下的用户或子部门'; |
||||
|
throw errMsg; |
||||
|
} |
||||
|
await models.Department.destroy({ where: { id: id } }); |
||||
|
await models.Department.destroy({ where: { dependence: id } }); |
||||
|
ctx.status = 204; |
||||
|
ctx.body = { message: '删除部门成功' } |
||||
|
} catch (error) { |
||||
|
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |
||||
|
ctx.status = 400; |
||||
|
ctx.body = { message: error } |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
async function getUser(ctx, next) { |
||||
|
try { |
||||
|
const models = ctx.fs.dc.models; |
||||
|
const { depId } = ctx.params; |
||||
|
let userRes = null; |
||||
|
if (depId !== 'null') { |
||||
|
userRes = await models.User.findAll({ |
||||
|
where: { |
||||
|
departmentId: parseInt(depId), |
||||
|
delete: false |
||||
|
}, |
||||
|
attributes: { exclude: ['password'] }, |
||||
|
order: [['id', 'asc']], |
||||
|
}) |
||||
|
} else { |
||||
|
userRes = await models.User.findAll({ |
||||
|
where: { |
||||
|
delete: false |
||||
|
}, |
||||
|
attributes: { exclude: ['password'] }, |
||||
|
order: [['id', 'asc']], |
||||
|
include: [{ |
||||
|
required: true, |
||||
|
model: models.Department, |
||||
|
attributes: ['id', 'name'], |
||||
|
}] |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
ctx.status = 200; |
||||
|
ctx.body = userRes |
||||
|
} catch (error) { |
||||
|
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |
||||
|
ctx.status = 400; |
||||
|
ctx.body = { |
||||
|
"message": "获取用户信息失败" |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
async function creatUser(ctx, next) { |
||||
|
let errMsg = "新建用户失败" |
||||
|
try { |
||||
|
const models = ctx.fs.dc.models; |
||||
|
const data = ctx.request.body; |
||||
|
|
||||
|
let repeatUserNameCount = await models.User.count({ |
||||
|
where: { |
||||
|
username: data.phone, |
||||
|
delete: false |
||||
|
} |
||||
|
}) |
||||
|
|
||||
|
if (repeatUserNameCount) { |
||||
|
errMsg = '已有当前用户名' |
||||
|
throw errMsg |
||||
|
} |
||||
|
|
||||
|
await models.User.create({ |
||||
|
name: data.name, |
||||
|
username: data.phone, |
||||
|
password: Hex.stringify(MD5(data.password)), |
||||
|
departmentId: data.departmentId, |
||||
|
email: data.email, |
||||
|
enable: data.enable, |
||||
|
delete: false, |
||||
|
phone: data.phone, |
||||
|
post: data.post, |
||||
|
}) |
||||
|
|
||||
|
ctx.status = 204; |
||||
|
} catch (error) { |
||||
|
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |
||||
|
ctx.status = 400; |
||||
|
ctx.body = { |
||||
|
"message": errMsg |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
async function updateUser(ctx, next) { |
||||
|
let errMsg = "修改用户失败" |
||||
|
try { |
||||
|
const models = ctx.fs.dc.models; |
||||
|
const data = ctx.request.body; |
||||
|
const { id } = ctx.params; |
||||
|
|
||||
|
let repeatUserNameCount = await models.User.count({ |
||||
|
where: { |
||||
|
username: data.username |
||||
|
} |
||||
|
}) |
||||
|
|
||||
|
if (repeatUserNameCount) { |
||||
|
errMsg = '已有当前用户名' |
||||
|
throw errMsg |
||||
|
} |
||||
|
|
||||
|
await models.User.update({ |
||||
|
name: data.name, |
||||
|
username: data.phone, |
||||
|
departmentId: data.departmentId, |
||||
|
email: data.email, |
||||
|
enable: data.enable, |
||||
|
delete: false, |
||||
|
phone: data.phone, |
||||
|
post: data.post, |
||||
|
}, { |
||||
|
where: { |
||||
|
id: id |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
ctx.status = 204; |
||||
|
} catch (error) { |
||||
|
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |
||||
|
ctx.status = 400; |
||||
|
ctx.body = { |
||||
|
"message": errMsg |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
async function deleteUser(ctx, next) { |
||||
|
try { |
||||
|
const models = ctx.fs.dc.models; |
||||
|
const { ids } = ctx.params; |
||||
|
const userIds = ids.split(','); |
||||
|
await models.User.update({ |
||||
|
delete: true, |
||||
|
}, { |
||||
|
where: { |
||||
|
id: { $in: userIds }, |
||||
|
} |
||||
|
}); |
||||
|
ctx.status = 204; |
||||
|
} catch (error) { |
||||
|
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |
||||
|
ctx.status = 400; |
||||
|
ctx.body = { |
||||
|
"message": "删除用户失败" |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
async function resetPwd(ctx, next) { |
||||
|
try { |
||||
|
const models = ctx.fs.dc.models; |
||||
|
const { id } = ctx.params; |
||||
|
const data = ctx.request.body; |
||||
|
await models.User.update({ |
||||
|
password: Hex.stringify(MD5(data.password)), |
||||
|
}, { |
||||
|
where: { |
||||
|
id: id, |
||||
|
} |
||||
|
}); |
||||
|
ctx.status = 204; |
||||
|
} catch (error) { |
||||
|
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |
||||
|
ctx.status = 400; |
||||
|
ctx.body = { |
||||
|
"message": "重置用户密码失败" |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 修改用户密码 |
||||
|
* @params {userId-用户Id} ctx |
||||
|
* @request.body {password-用户新密码} ctx |
||||
|
*/ |
||||
|
async function updateUserPassword(ctx, next) { |
||||
|
try { |
||||
|
const models = ctx.fs.dc.models; |
||||
|
const { userId } = ctx.params; |
||||
|
const { password } = ctx.request.body; |
||||
|
if (!password) { |
||||
|
ctx.status = 400; |
||||
|
ctx.body = { "message": "请输入修改密码" }; |
||||
|
return; |
||||
|
} |
||||
|
const userRes = await models.User.findOne({ |
||||
|
where: { |
||||
|
id: userId |
||||
|
}, |
||||
|
attributes: ['id'] |
||||
|
}); |
||||
|
if (userRes) { |
||||
|
await models.User.update({ password: Hex.stringify(MD5(password)) }, { where: { id: userId, } }); |
||||
|
ctx.status = 204; |
||||
|
} else { |
||||
|
ctx.status = 400; |
||||
|
ctx.body = { |
||||
|
"message": "用户不存在" |
||||
|
} |
||||
|
} |
||||
|
} catch (error) { |
||||
|
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |
||||
|
ctx.status = 400; |
||||
|
ctx.body = { |
||||
|
"message": "修改用户密码失败" |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
module.exports = { |
||||
|
getDepMessage, |
||||
|
createDept, |
||||
|
updateDept, |
||||
|
delDept, |
||||
|
getUser, |
||||
|
creatUser, |
||||
|
updateUser, |
||||
|
deleteUser, |
||||
|
resetPwd, |
||||
|
updateUserPassword |
||||
|
} |
@ -0,0 +1,122 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
async function getPatrolPlan(ctx, next) { |
||||
|
try { |
||||
|
const models = ctx.fs.dc.models; |
||||
|
const { limit, page } = ctx.query; |
||||
|
let options = { |
||||
|
include: [{ |
||||
|
required: true, |
||||
|
model: models.User, |
||||
|
attributes: ['id', 'name'], |
||||
|
include: [{ |
||||
|
required: true, |
||||
|
model: models.Department, |
||||
|
attributes: ['id', 'name'], |
||||
|
}] |
||||
|
}, { |
||||
|
required: true, |
||||
|
model: models.Project, |
||||
|
attributes: ['id', 'name'], |
||||
|
}] |
||||
|
}; |
||||
|
if (limit) { |
||||
|
options.limit = Number(limit); |
||||
|
} |
||||
|
if (page && limit) { |
||||
|
options.offset = Number(page) * Number(limit); |
||||
|
} |
||||
|
let res = await models.PatrolPlan.findAndCountAll(options); |
||||
|
ctx.status = 200; |
||||
|
ctx.body = res; |
||||
|
} catch (error) { |
||||
|
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |
||||
|
ctx.status = 400; |
||||
|
ctx.body = { |
||||
|
"message": "获取巡检计划失败" |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
async function createPatrolPlan(ctx, next) { |
||||
|
try { |
||||
|
const models = ctx.fs.dc.models; |
||||
|
const data = ctx.request.body; |
||||
|
const { name, way, structureId, startTime, endTime, frequency, points, userId } = data; |
||||
|
|
||||
|
let plan = { name, way, structureId, startTime, endTime, frequency, points, userId }; |
||||
|
|
||||
|
await models.PatrolPlan.create(plan); |
||||
|
|
||||
|
ctx.status = 204; |
||||
|
} catch (error) { |
||||
|
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |
||||
|
ctx.status = 400; |
||||
|
ctx.body = { |
||||
|
"message": '新增巡检计划失败' |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
async function updatePatrolPlan(ctx, next) { |
||||
|
try { |
||||
|
let errMsg = '修改巡检计划失败'; |
||||
|
const models = ctx.fs.dc.models; |
||||
|
const data = ctx.request.body; |
||||
|
const { name, way, structureId, startTime, endTime, frequency, points, userId } = data; |
||||
|
|
||||
|
let plan = { name, way, structureId, startTime, endTime, frequency, points, userId }; |
||||
|
|
||||
|
if (data && data.id) { |
||||
|
await models.PatrolPlan.update(plan, { |
||||
|
where: { id: data.id } |
||||
|
}) |
||||
|
} else { |
||||
|
errMsg = '请传入巡检计划id'; |
||||
|
throw errMsg; |
||||
|
} |
||||
|
|
||||
|
ctx.status = 204; |
||||
|
} catch (error) { |
||||
|
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |
||||
|
ctx.status = 400; |
||||
|
ctx.body = { |
||||
|
"message": errMsg |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
async function delPatrolPlan(ctx, next) { |
||||
|
try { |
||||
|
let errMsg = '删除巡检计划失败'; |
||||
|
|
||||
|
const models = ctx.fs.dc.models; |
||||
|
const { id } = ctx.params; |
||||
|
|
||||
|
const record = await models.PatrolRecord.findOne({ |
||||
|
where: { patrolPlanId: id } |
||||
|
}); |
||||
|
|
||||
|
if (record) { |
||||
|
errMsg = '不能删除有巡检记录的计划'; |
||||
|
throw errMsg; |
||||
|
} |
||||
|
|
||||
|
await models.PatrolPlan.destroy({ |
||||
|
where: { id } |
||||
|
}) |
||||
|
|
||||
|
ctx.status = 204; |
||||
|
} catch (error) { |
||||
|
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |
||||
|
ctx.status = 400; |
||||
|
ctx.body = { message: error } |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
module.exports = { |
||||
|
getPatrolPlan, |
||||
|
createPatrolPlan, |
||||
|
updatePatrolPlan, |
||||
|
delPatrolPlan, |
||||
|
} |
@ -0,0 +1,113 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
async function findPatrolRecord(ctx, next) { |
||||
|
let rslt = []; |
||||
|
let error = { name: 'FindError', message: '获取巡检记录失败' }; |
||||
|
try { |
||||
|
const models = ctx.fs.dc.models; |
||||
|
const { startTime, endTime, alarm, patrolPlanId, pointId } = ctx.params; |
||||
|
// patrolPlanId传all查所有
|
||||
|
if (patrolPlanId == 'all') { |
||||
|
/* 如果有startTime && endTime,查询所有符合条件的数据 */ |
||||
|
if (startTime !== 'null' && endTime !== 'null') { |
||||
|
if (pointId !== 'null') { |
||||
|
if (alarm == 'null') { |
||||
|
rslt = await models.PatrolRecord.findAll({ |
||||
|
where: { inspectionTime: { $between: [startTime, endTime] }, pointId: { $in: pointId.split(',') } }, |
||||
|
}); |
||||
|
} else { |
||||
|
rslt = await models.PatrolRecord.findAll({ |
||||
|
where: { alarm, inspectionTime: { $between: [startTime, endTime] }, pointId: { $in: pointId.split(',') } }, |
||||
|
}); |
||||
|
} |
||||
|
} else { |
||||
|
if (alarm == 'null') { |
||||
|
rslt = await models.PatrolRecord.findAll({ |
||||
|
where: { inspectionTime: { $between: [startTime, endTime] } }, |
||||
|
}); |
||||
|
} else { |
||||
|
rslt = await models.PatrolRecord.findAll({ |
||||
|
where: { alarm, inspectionTime: { $between: [startTime, endTime] } }, |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
} else { |
||||
|
/* 如果没有startTime && endTime,查询每个点位最新一条符合条件的数据 */ |
||||
|
let a = [] |
||||
|
if (pointId !== 'null') { |
||||
|
a = await models.PatrolRecord.findAll({ |
||||
|
where: { pointId: { $in: pointId.split(',') } }, |
||||
|
}); |
||||
|
} |
||||
|
rslt = pointId.split(',').map(i => { |
||||
|
return a.filter(t => t.pointId == i).sort((a, b) => b.id - a.id)[0] || null |
||||
|
}) |
||||
|
} |
||||
|
} else { |
||||
|
if (startTime !== 'null' && endTime !== 'null') { |
||||
|
if (pointId !== 'null') { |
||||
|
rslt = await models.PatrolRecord.findAll({ |
||||
|
where: { patrolPlanId: { $in: patrolPlanId.split(',') }, alarm, inspectionTime: { $between: [startTime, endTime] }, pointId: { $in: pointId.split(',') } }, |
||||
|
}); |
||||
|
} else { |
||||
|
rslt = await models.PatrolRecord.findAll({ |
||||
|
where: { patrolPlanId: { $in: patrolPlanId.split(',') }, alarm, inspectionTime: { $between: [startTime, endTime] } }, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
} else { |
||||
|
let a = [] |
||||
|
/* 如果没有startTime && endTime,查询每个点位最新一条符合条件的数据 */ |
||||
|
if (pointId !== 'null') { |
||||
|
a = await models.PatrolRecord.findAll({ |
||||
|
where: { patrolPlanId: { $in: patrolPlanId.split(',') }, pointId: { $in: pointId.split(',') } }, |
||||
|
}); |
||||
|
} else { |
||||
|
a = await models.PatrolRecord.findAll({ |
||||
|
where: { patrolPlanId: { $in: patrolPlanId.split(',') } }, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
rslt = pointId.split(',').map(i => { |
||||
|
return a.filter(t => t.pointId == i).sort((a, b) => b.id - a.id)[0] || null |
||||
|
}) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
ctx.status = 200; |
||||
|
ctx.body = rslt; |
||||
|
error = null |
||||
|
} catch (error) { |
||||
|
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |
||||
|
ctx.status = 400; |
||||
|
ctx.body = { |
||||
|
"message": "获取巡检记录失败" |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
async function addPatrolRecord(ctx, next) { |
||||
|
let error = { name: 'addError', message: '新增巡检记录失败' }; |
||||
|
try { |
||||
|
const models = ctx.fs.dc.models; |
||||
|
const data = ctx.request.body; |
||||
|
let { patrolPlanId, lastInspectionTime, inspectionTime, points, alarm, pointId } = data |
||||
|
let record = { patrolPlanId, lastInspectionTime, inspectionTime, points, alarm, pointId } |
||||
|
|
||||
|
await models.PatrolRecord.create(record); |
||||
|
|
||||
|
ctx.status = 204; |
||||
|
error = null |
||||
|
} catch (error) { |
||||
|
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |
||||
|
ctx.status = 400; |
||||
|
ctx.body = { |
||||
|
"message": '新增巡检计划失败' |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
module.exports = { |
||||
|
findPatrolRecord, |
||||
|
addPatrolRecord, |
||||
|
} |
@ -0,0 +1,431 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
|
||||
|
async function projectList (ctx, next) { |
||||
|
try { |
||||
|
const models = ctx.fs.dc.models; |
||||
|
let userInfo = ctx.fs.api.userInfo; |
||||
|
const { limit, page, name, justStructure } = ctx.query; |
||||
|
|
||||
|
let options = { |
||||
|
where: { |
||||
|
|
||||
|
}, |
||||
|
// include: [{
|
||||
|
// as: 'company',
|
||||
|
// model: models.Company,
|
||||
|
// attributes: ['id', 'name'],
|
||||
|
// },],
|
||||
|
} |
||||
|
if (limit) { |
||||
|
options.limit = Number(limit) |
||||
|
} |
||||
|
if (page && limit) { |
||||
|
options.offset = Number(page) * Number(limit) |
||||
|
} |
||||
|
if (name) { |
||||
|
options.where.name = { $like: `%${name}%` } |
||||
|
} |
||||
|
|
||||
|
let res = [] |
||||
|
if (justStructure) { |
||||
|
res = await models.Project.findAndCountAll({ |
||||
|
attributes: ['id', 'name'], |
||||
|
}) |
||||
|
} else { |
||||
|
res = await models.Project.findAndCountAll(options) |
||||
|
} |
||||
|
|
||||
|
ctx.status = 200; |
||||
|
ctx.body = res |
||||
|
} catch (error) { |
||||
|
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |
||||
|
ctx.status = 400; |
||||
|
ctx.body = { |
||||
|
"message": "获取结构列表失败" |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
async function postAddProject (ctx, next) { |
||||
|
try { |
||||
|
const models = ctx.fs.dc.models; |
||||
|
let userInfo = ctx.fs.api.userInfo; |
||||
|
const data = ctx.request.body; |
||||
|
const { img, longitude, latitude, name, type, describe } = data |
||||
|
|
||||
|
let errMsg = data.id ? '结构物编辑失败' : '结构物新增失败' |
||||
|
let project = { img, longitude, latitude, name, type, describe, userId: userInfo.id } |
||||
|
|
||||
|
const alikeProject = await models.Project.findOne({ |
||||
|
where: { |
||||
|
name: name, |
||||
|
} |
||||
|
}) |
||||
|
|
||||
|
if ((!data.id && alikeProject) || (alikeProject && alikeProject.id !== data.id)) { |
||||
|
errMsg = '已有相同结构物名称' |
||||
|
throw errMsg |
||||
|
} |
||||
|
if (data && data.id) { |
||||
|
await models.Project.update(project, { |
||||
|
where: { |
||||
|
id: data.id |
||||
|
} |
||||
|
}) |
||||
|
} else { |
||||
|
await models.Project.create(project) |
||||
|
} |
||||
|
|
||||
|
|
||||
|
ctx.status = 204; |
||||
|
} catch (error) { |
||||
|
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`) |
||||
|
ctx.status = 400; |
||||
|
ctx.body = { |
||||
|
"message": errMsg |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
async function delProject (ctx, next) { |
||||
|
try { |
||||
|
const models = ctx.fs.dc.models; |
||||
|
let userInfo = ctx.fs.api.userInfo; |
||||
|
const { id } = ctx.params |
||||
|
|
||||
|
//删除结构物
|
||||
|
await models.Project.destroy({ |
||||
|
where: { |
||||
|
id, |
||||
|
} |
||||
|
}) |
||||
|
const pointId = [] |
||||
|
const pointLIst = await models.Point.findAll({ |
||||
|
where: { |
||||
|
projectId: id, |
||||
|
}, |
||||
|
attributes: ['id'], |
||||
|
}) |
||||
|
pointLIst.map(v => pointId.push(v.id)) |
||||
|
|
||||
|
//点位
|
||||
|
await models.Point.destroy({ |
||||
|
where: { |
||||
|
projectId: id |
||||
|
} |
||||
|
}) |
||||
|
|
||||
|
|
||||
|
//巡检计划
|
||||
|
const planId = [] |
||||
|
const planLIst = await models.PatrolPlan.findAll({ |
||||
|
where: { |
||||
|
structureId: id, |
||||
|
}, |
||||
|
attributes: ['id'], |
||||
|
}) |
||||
|
planLIst.map(v => planId.push(v.id)) |
||||
|
await models.PatrolPlan.destroy({ |
||||
|
where: { |
||||
|
structureId: id |
||||
|
} |
||||
|
}) |
||||
|
|
||||
|
//巡检记录
|
||||
|
await models.PatrolRecord.destroy({ |
||||
|
where: { |
||||
|
pointId: { $in: pointId }, |
||||
|
patrolPlanId: { $in: planId } |
||||
|
} |
||||
|
}) |
||||
|
|
||||
|
|
||||
|
ctx.status = 204; |
||||
|
} catch (error) { |
||||
|
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`) |
||||
|
ctx.status = 400; |
||||
|
ctx.body = { |
||||
|
"message": '删除结构物失败' |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
async function addPosition (ctx, next) { |
||||
|
try { |
||||
|
const models = ctx.fs.dc.models; |
||||
|
let userInfo = ctx.fs.api.userInfo; |
||||
|
const data = ctx.request.body; |
||||
|
const { longitude, latitude, name, describe, qrCode, projectId, } = data |
||||
|
|
||||
|
let errMsg = data.id ? '点位编辑失败' : '点位新增失败' |
||||
|
let pointData = { longitude, latitude, name, describe, qrCode, projectId } |
||||
|
|
||||
|
const alikeProject = await models.Point.findOne({ |
||||
|
where: { |
||||
|
id: data.id, |
||||
|
} |
||||
|
}) |
||||
|
|
||||
|
if (data && data.id) { |
||||
|
if (qrCode) { |
||||
|
await models.Point.update({ ...alikeProject, qrCode }, { |
||||
|
where: { |
||||
|
id: data.id, |
||||
|
} |
||||
|
}) |
||||
|
} else { |
||||
|
await models.Point.update({ pointData }, { |
||||
|
where: { |
||||
|
id: data.id, |
||||
|
} |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
} else { |
||||
|
await models.Point.create(pointData) |
||||
|
} |
||||
|
|
||||
|
|
||||
|
ctx.status = 204; |
||||
|
} catch (error) { |
||||
|
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`) |
||||
|
ctx.status = 400; |
||||
|
ctx.body = { |
||||
|
"message": errMsg |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
async function position (ctx, next) { |
||||
|
try { |
||||
|
const models = ctx.fs.dc.models; |
||||
|
let userInfo = ctx.fs.api.userInfo; |
||||
|
const { limit, page, projectId } = ctx.query; |
||||
|
|
||||
|
let options = { |
||||
|
where: { |
||||
|
id: projectId |
||||
|
}, |
||||
|
include: [{ |
||||
|
model: models.Point, |
||||
|
},], |
||||
|
} |
||||
|
if (limit) { |
||||
|
options.limit = Number(limit) |
||||
|
} |
||||
|
if (page && limit) { |
||||
|
options.offset = Number(page) * Number(limit) |
||||
|
} |
||||
|
|
||||
|
let res = await models.Project.findAndCountAll(options) |
||||
|
ctx.status = 200; |
||||
|
ctx.body = res |
||||
|
} catch (error) { |
||||
|
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |
||||
|
ctx.status = 400; |
||||
|
ctx.body = { |
||||
|
"message": "获取结构列表失败" |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
async function delPosition (ctx, next) { |
||||
|
try { |
||||
|
const models = ctx.fs.dc.models; |
||||
|
let userInfo = ctx.fs.api.userInfo; |
||||
|
const { id } = ctx.params |
||||
|
|
||||
|
const pointOne = await models.Point.findOne({ |
||||
|
where: { |
||||
|
id |
||||
|
}, |
||||
|
attributes: ['projectId'], |
||||
|
}) |
||||
|
if (pointOne) { |
||||
|
const patrolPlanLIst = await models.PatrolPlan.findAll({ |
||||
|
where: { |
||||
|
structureId: pointOne.projectId, |
||||
|
}, |
||||
|
}) |
||||
|
|
||||
|
for (var u of patrolPlanLIst) { |
||||
|
const points = [] |
||||
|
u.points.map(r => { |
||||
|
if (r.id == id) { |
||||
|
} else { |
||||
|
points.push(r) |
||||
|
} |
||||
|
}) |
||||
|
u.points = points |
||||
|
|
||||
|
await models.PatrolRecord.destroy({ |
||||
|
where: { |
||||
|
pointId: id, |
||||
|
patrolPlanId: u.id |
||||
|
} |
||||
|
}) |
||||
|
|
||||
|
if (points.length > 0) { |
||||
|
let data = { |
||||
|
name: u.dataValues.name, |
||||
|
way: u.dataValues.way, |
||||
|
structureId: u.dataValues.structureId, |
||||
|
startTime: u.dataValues.startTime, |
||||
|
endTime: u.dataValues.endTime, |
||||
|
frequency: u.dataValues.frequency, |
||||
|
points: u.dataValues.points, |
||||
|
userId: u.dataValues.userId, |
||||
|
patrolCount: u.dataValues.patrolCount |
||||
|
} |
||||
|
await models.PatrolPlan.update(data,{ |
||||
|
where: { |
||||
|
id: u.dataValues.id |
||||
|
} |
||||
|
}) |
||||
|
} else { |
||||
|
await models.PatrolPlan.destroy({ |
||||
|
where: { |
||||
|
id: u.id |
||||
|
} |
||||
|
}) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
await models.Point.destroy({ |
||||
|
where: { |
||||
|
id, |
||||
|
} |
||||
|
}) |
||||
|
|
||||
|
|
||||
|
ctx.status = 204; |
||||
|
} catch (error) { |
||||
|
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`) |
||||
|
ctx.status = 400; |
||||
|
ctx.body = { |
||||
|
"message": '删除点位失败' |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
async function qrCodeShow (ctx, next) { |
||||
|
try { |
||||
|
const models = ctx.fs.dc.models; |
||||
|
let userInfo = ctx.fs.api.userInfo; |
||||
|
const { projectId, name } = ctx.query; |
||||
|
|
||||
|
let options = { |
||||
|
where: { |
||||
|
qrCode: { $ne: null } |
||||
|
}, |
||||
|
} |
||||
|
if (projectId) { |
||||
|
options.where.projectId = projectId |
||||
|
} |
||||
|
if (name) { |
||||
|
options.where.name = { $like: `%${name}%` } |
||||
|
} |
||||
|
|
||||
|
let res = await models.Point.findAndCountAll(options) |
||||
|
ctx.status = 200; |
||||
|
ctx.body = res |
||||
|
} catch (error) { |
||||
|
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |
||||
|
ctx.status = 400; |
||||
|
ctx.body = { |
||||
|
"message": "获取二维码列表失败" |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
async function q (ctx) { |
||||
|
// let error = {
|
||||
|
// name: 'FindError',
|
||||
|
// message: "获取失败!"
|
||||
|
// };
|
||||
|
// const models = ctx.fs.dc.models;
|
||||
|
// const { devices } = ctx.request.body
|
||||
|
// const attachment = ctx.app.fs.qn_attachment
|
||||
|
|
||||
|
// try {
|
||||
|
|
||||
|
// if (!Array.isArray(devices)) {
|
||||
|
// error = { name: 'paramsError', message: '参数不能为空' };
|
||||
|
// ctx.throw(400);
|
||||
|
// }
|
||||
|
// const devicesArr = await models.Device.findAll({
|
||||
|
// attributes: ['deviceNo', 'periodCode', 'qrSrc'],
|
||||
|
// where: { deviceNo: { $in: devices } }
|
||||
|
// })
|
||||
|
|
||||
|
// let ids = [], idsMap = {}, qnImages = []
|
||||
|
// devicesArr.forEach(d => {
|
||||
|
// const qrSrc = d.qrSrc
|
||||
|
// const deviceNo = d.deviceNo
|
||||
|
// const periodCode = d.periodCode
|
||||
|
// if (qrSrc) {
|
||||
|
// if (/^\d+$/.test(qrSrc)) {
|
||||
|
// ids.push(qrSrc)
|
||||
|
// idsMap[qrSrc] = { deviceNo, periodCode }
|
||||
|
// } else {
|
||||
|
// let domain = globalCache.getQnDomain()
|
||||
|
// let imgUrl = `${domain}/${qrSrc}`
|
||||
|
// qnImages.push({ src: imgUrl, deviceNo, periodCode })
|
||||
|
// }
|
||||
|
// }
|
||||
|
// })
|
||||
|
|
||||
|
// const docs = await models.QrcodePng.findAll({
|
||||
|
// where: {
|
||||
|
// id: { $in: ids }
|
||||
|
// },
|
||||
|
// attributes: ["id", "base64"]
|
||||
|
// })
|
||||
|
|
||||
|
// let pics = []
|
||||
|
|
||||
|
// if (docs.length > 0) {
|
||||
|
// pics = docs.map((d) => {
|
||||
|
// let { deviceNo, periodCode } = idsMap[d.id] || {}
|
||||
|
// let base64 = d.base64.replace(/^data:image\/\w+;base64,/, '')
|
||||
|
// return {
|
||||
|
// url: Buffer.from(base64, 'base64'),
|
||||
|
// name: deviceNo,
|
||||
|
// periodCode
|
||||
|
// }
|
||||
|
// })
|
||||
|
// }
|
||||
|
|
||||
|
// if (qnImages.length > 0) {
|
||||
|
// let qns = await downloadImgsAsBase64(qnImages)
|
||||
|
// pics = pics.concat(qns)
|
||||
|
// }
|
||||
|
|
||||
|
// let fileUrl = await downLoadImageBiz(pics, { zipName: "二维码_" + moment().format("YYYY-MM-DD-HH-mm-ss"), attachment })
|
||||
|
// add2CleanCache(fileUrl, attachment)
|
||||
|
// ctx.status = 200
|
||||
|
// ctx.body = { fileUrl }
|
||||
|
|
||||
|
// } catch (err) {
|
||||
|
// ctx.fs.logger.error(err);
|
||||
|
// ctx.status = 400;
|
||||
|
// ctx.body = error;
|
||||
|
// }
|
||||
|
} |
||||
|
|
||||
|
module.exports = { |
||||
|
projectList, |
||||
|
postAddProject, |
||||
|
delProject, |
||||
|
addPosition, |
||||
|
position, |
||||
|
delPosition, |
||||
|
qrCodeShow, |
||||
|
q |
||||
|
} |
@ -0,0 +1,77 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
const fs = require('fs'); |
||||
|
const path = require('path'); |
||||
|
const utils = require('./utils') |
||||
|
const routes = require('./routes'); |
||||
|
//const redisConnect = require('./service/redis')
|
||||
|
const socketConect = require('./service/socket') |
||||
|
//const paasRequest = require('./service/paasRequest');
|
||||
|
const authenticator = require('./middlewares/authenticator'); |
||||
|
//const clickHouseClient = require('./service/clickHouseClient')
|
||||
|
const schedule = require('./schedule') |
||||
|
// const apiLog = require('./middlewares/api-log');
|
||||
|
|
||||
|
module.exports.entry = function (app, router, opts) { |
||||
|
app.fs.logger.log('info', '[FS-AUTH]', 'Inject auth and api mv into router.'); |
||||
|
|
||||
|
app.fs.api = app.fs.api || {}; |
||||
|
app.fs.opts = opts || {}; |
||||
|
app.fs.utils = app.fs.utils || {}; |
||||
|
app.fs.api.authAttr = app.fs.api.authAttr || {}; |
||||
|
app.fs.api.logAttr = app.fs.api.logAttr || {}; |
||||
|
|
||||
|
// 顺序固定 ↓
|
||||
|
//redisConnect(app, opts)
|
||||
|
socketConect(app, opts) |
||||
|
|
||||
|
// 实例其他平台请求方法
|
||||
|
//paasRequest(app, opts)
|
||||
|
|
||||
|
// clickHouse 数据库 client
|
||||
|
//clickHouseClient(app, opts)
|
||||
|
|
||||
|
// 工具类函数
|
||||
|
utils(app, opts) |
||||
|
|
||||
|
// 定时任务
|
||||
|
schedule(app, opts) |
||||
|
|
||||
|
//鉴权中间件
|
||||
|
router.use(authenticator(app, opts)); |
||||
|
|
||||
|
// 日志记录
|
||||
|
// router.use(apiLog(app, opts));
|
||||
|
|
||||
|
router = routes(app, router, opts); |
||||
|
}; |
||||
|
|
||||
|
module.exports.models = function (dc) { // dc = { orm: Sequelize对象, ORM: Sequelize, models: {} }
|
||||
|
|
||||
|
// 模型关系摘出来 初始化之后再定义关系才行
|
||||
|
fs.readdirSync(path.join(__dirname, '/models')).forEach((filename) => { |
||||
|
require(`./models/${filename}`)(dc) |
||||
|
}); |
||||
|
|
||||
|
const { Department, User, UserResource, Resource, Project, Point, PatrolPlan |
||||
|
} = dc.models; |
||||
|
|
||||
|
UserResource.belongsTo(User, { foreignKey: 'userId', targetKey: 'id' }); |
||||
|
User.hasMany(UserResource, { foreignKey: 'userId', sourceKey: 'id' }); |
||||
|
|
||||
|
UserResource.belongsTo(Resource, { foreignKey: 'resourceId', targetKey: 'code' }); |
||||
|
Resource.hasMany(UserResource, { foreignKey: 'resourceId', sourceKey: 'code' }); |
||||
|
Resource.hasMany(Resource, { foreignKey: 'parentResource', sourceKey: 'code' }); |
||||
|
|
||||
|
User.belongsTo(Department, { foreignKey: 'departmentId', targetKey: 'id' }); |
||||
|
Department.hasMany(User, { foreignKey: 'departmentId', sourceKey: 'id' }); |
||||
|
|
||||
|
Point.belongsTo(Project, { foreignKey: 'projectId', targetKey: 'id' }); |
||||
|
Project.hasMany(Point, { foreignKey: 'projectId', sourceKey: 'id' }); |
||||
|
|
||||
|
PatrolPlan.belongsTo(Project, { foreignKey: 'structureId', targetKey: 'id' }); |
||||
|
Project.hasMany(PatrolPlan, { foreignKey: 'structureId', sourceKey: 'id' }); |
||||
|
|
||||
|
PatrolPlan.belongsTo(User, { foreignKey: 'userId', targetKey: 'id' }); |
||||
|
User.hasMany(PatrolPlan, { foreignKey: 'userId', sourceKey: 'id' }); |
||||
|
}; |
@ -0,0 +1,83 @@ |
|||||
|
/** |
||||
|
* Created by PengPeng on 2017/4/26. |
||||
|
*/ |
||||
|
'use strict'; |
||||
|
|
||||
|
const moment = require('moment'); |
||||
|
const pathToRegexp = require('path-to-regexp'); |
||||
|
|
||||
|
function factory(app, opts) { |
||||
|
async function sendToEsAsync(producer, payloads) { |
||||
|
return new Promise((resolve, reject) => { |
||||
|
producer.send(payloads, function (err) { |
||||
|
if (err) { |
||||
|
reject(err); |
||||
|
} else { |
||||
|
resolve(); |
||||
|
} |
||||
|
}); |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
async function logger(ctx, next) { |
||||
|
const { path, method } = ctx; |
||||
|
const start = Date.now(); |
||||
|
|
||||
|
// 等待路由处理
|
||||
|
await next(); |
||||
|
|
||||
|
try { |
||||
|
let logAttr = null; |
||||
|
for (let prop in app.fs.api.logAttr) { |
||||
|
let keys = []; |
||||
|
let re = pathToRegexp(prop.replace(/\:[A-Za-z_\-]+\b/g, '(\\d+)'), keys); |
||||
|
if (re.test(`${method}${path}`)) { |
||||
|
logAttr = app.fs.api.logAttr[prop]; |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
let parameter = null, parameterShow = null, user_id, _token, app_key; |
||||
|
if (ctx.fs.api) { |
||||
|
const { actionParameter, actionParameterShow, userId, token, appKey } = ctx.fs.api; |
||||
|
parameter = actionParameter; |
||||
|
parameterShow = actionParameterShow; |
||||
|
user_id = userId; |
||||
|
_token = token; |
||||
|
app_key = appKey; |
||||
|
} |
||||
|
const producer = ctx.fs.kafka.producer; |
||||
|
|
||||
|
const message = { |
||||
|
log_time: moment().toISOString(), |
||||
|
method: method, |
||||
|
content: logAttr ? logAttr.content : '', |
||||
|
parameter: JSON.stringify(parameter) || JSON.stringify(ctx.request.body), |
||||
|
parameter_show: parameterShow, |
||||
|
visible: logAttr ? logAttr.visible : true, |
||||
|
cost: Date.now() - start, |
||||
|
status_code: ctx.status, |
||||
|
url: ctx.request.url, |
||||
|
user_agent: ctx.request.headers["user-agent"], |
||||
|
user_id: user_id, |
||||
|
session: _token, |
||||
|
app_key: app_key, |
||||
|
header: JSON.stringify(ctx.request.headers), |
||||
|
ip: ctx.request.headers["x-real-ip"] || ctx.ip |
||||
|
}; |
||||
|
|
||||
|
const payloads = [{ |
||||
|
topic: `${opts.kafka.topicPrefix}`, |
||||
|
messages: [JSON.stringify(message)], |
||||
|
partition: 0 |
||||
|
}]; |
||||
|
|
||||
|
// await sendToEsAsync(producer, payloads);
|
||||
|
|
||||
|
} catch (e) { |
||||
|
ctx.fs.logger.error(`日志记录失败: ${e}`); |
||||
|
} |
||||
|
} |
||||
|
return logger; |
||||
|
} |
||||
|
|
||||
|
module.exports = factory; |
@ -0,0 +1,149 @@ |
|||||
|
/** |
||||
|
* Created by PengLing on 2017/3/27. |
||||
|
*/ |
||||
|
'use strict'; |
||||
|
|
||||
|
const pathToRegexp = require('path-to-regexp'); |
||||
|
const util = require('util'); |
||||
|
const moment = require('moment'); |
||||
|
|
||||
|
class ExcludesUrls { |
||||
|
constructor(opts) { |
||||
|
this.allUrls = undefined; |
||||
|
this.reload(opts); |
||||
|
} |
||||
|
|
||||
|
sanitizePath (path) { |
||||
|
if (!path) return '/'; |
||||
|
const p = '/' + path.replace(/^\/+/i, '').replace(/\/+$/, '').replace(/\/{2,}/, '/'); |
||||
|
return p; |
||||
|
} |
||||
|
|
||||
|
reload (opts) { |
||||
|
// load all url
|
||||
|
if (!this.allUrls) { |
||||
|
this.allUrls = opts; |
||||
|
let that = this; |
||||
|
this.allUrls.forEach(function (url, i, arr) { |
||||
|
if (typeof url === "string") { |
||||
|
url = { p: url, o: '*' }; |
||||
|
arr[i] = url; |
||||
|
} |
||||
|
const keys = []; |
||||
|
let eachPath = url.p; |
||||
|
url.p = (!eachPath || eachPath === '(.*)' || util.isRegExp(eachPath)) ? eachPath : that.sanitizePath(eachPath); |
||||
|
url.pregexp = pathToRegexp(eachPath, keys); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
isExcluded (path, method) { |
||||
|
return this.allUrls.some(function (url) { |
||||
|
return !url.auth |
||||
|
&& url.pregexp.test(path) |
||||
|
&& (url.o === '*' || url.o.indexOf(method) !== -1); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 判断Url是否不鉴权 |
||||
|
* @param {*} opts {exclude: [*] or []},'*'或['*']:跳过所有路由; []:所有路由都要验证 |
||||
|
* @param {*} path 当前request的path |
||||
|
* @param {*} method 当前request的method |
||||
|
*/ |
||||
|
let isPathExcluded = function (opts, path, method) { |
||||
|
let excludeAll = Boolean(opts.exclude && opts.exclude.length && opts.exclude[0] == '*'); |
||||
|
let excludes = null; |
||||
|
if (!excludeAll) { |
||||
|
let excludeOpts = opts.exclude || []; |
||||
|
excludeOpts.push({ p: '/login', o: 'POST' }); |
||||
|
excludeOpts.push({ p: '/logout', o: 'PUT' }); |
||||
|
excludes = new ExcludesUrls(excludeOpts); |
||||
|
} |
||||
|
let excluded = excludeAll || excludes.isExcluded(path, method); |
||||
|
return excluded; |
||||
|
}; |
||||
|
|
||||
|
let authorizeToken = async function (ctx, token) { |
||||
|
let rslt = null; |
||||
|
const tokenFormatRegexp = /^(\{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\}{0,1})$/g; |
||||
|
if (token && tokenFormatRegexp.test(token)) { |
||||
|
try { |
||||
|
|
||||
|
const authorizeRes = await ctx.fs.dc.models.UserToken.findOne({ |
||||
|
where: { |
||||
|
token: token |
||||
|
} |
||||
|
}) |
||||
|
const { userInfo, expired } = authorizeRes; |
||||
|
|
||||
|
if (expired && moment().valueOf() <= moment(expired).valueOf()) { |
||||
|
rslt = { |
||||
|
'authorized': userInfo.authorized, |
||||
|
'resources': (userInfo || {}).resources || [], |
||||
|
}; |
||||
|
ctx.fs.api.userId = userInfo.id; |
||||
|
ctx.fs.api.userInfo = userInfo; |
||||
|
ctx.fs.api.token = token; |
||||
|
} |
||||
|
} catch (err) { |
||||
|
const { error } = err.response || {}; |
||||
|
ctx.fs.logger.log('[anxinyun]', '[AUTH] failed', (error || {}).message || `cannot GET /users/${token}`); |
||||
|
} |
||||
|
} |
||||
|
return rslt; |
||||
|
}; |
||||
|
|
||||
|
let isResourceAvailable = function (resources, options) { |
||||
|
let authCode = null; |
||||
|
// authorize user by authorization attribute
|
||||
|
const { authAttr, method, path } = options; |
||||
|
for (let prop in authAttr) { |
||||
|
let keys = []; |
||||
|
let re = pathToRegexp(prop.replace(/\:[A-Za-z_\-]+\b/g, '(\\d+)'), keys); |
||||
|
if (re.test(`${method}${path}`)) { |
||||
|
authCode = authAttr[prop]; |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
return !authCode || (resources || []).some(code => code === authCode); |
||||
|
}; |
||||
|
|
||||
|
function factory (app, opts) { |
||||
|
return async function auth (ctx, next) { |
||||
|
const { path, method, header, query } = ctx; |
||||
|
ctx.fs.logger.log('[AUTH] start', path, method); |
||||
|
ctx.fs.api = ctx.fs.api || {}; |
||||
|
ctx.fs.port = opts.port; |
||||
|
ctx.redis = app.redis; |
||||
|
ctx.redisTools = app.redisTools; |
||||
|
let error = null; |
||||
|
if (path) { |
||||
|
if (!isPathExcluded(opts, path, method)) { |
||||
|
const user = await authorizeToken(ctx, header.token || query.token); |
||||
|
if (user && user.authorized) { |
||||
|
// if (!isResourceAvailable(user.resources, { authAttr: app.fs.auth.authAttr, path, method })) {
|
||||
|
// error = { status: 403, name: 'Forbidden' }
|
||||
|
// } else {
|
||||
|
// error = { status: 401, name: 'Unauthorized' }
|
||||
|
// }
|
||||
|
} else { |
||||
|
error = { status: 401, name: 'Unauthorized' } |
||||
|
} |
||||
|
} |
||||
|
} else { |
||||
|
error = { status: 401, name: 'Unauthorized' }; |
||||
|
} |
||||
|
if (error) { |
||||
|
ctx.fs.logger.log('[AUTH] failed', path, method); |
||||
|
ctx.status = error.status; |
||||
|
ctx.body = error.name; |
||||
|
} else { |
||||
|
ctx.fs.logger.log('[AUTH] passed', path, method); |
||||
|
await next(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
module.exports = factory; |
@ -0,0 +1,56 @@ |
|||||
|
/* eslint-disable*/ |
||||
|
'use strict'; |
||||
|
|
||||
|
module.exports = dc => { |
||||
|
const DataTypes = dc.ORM; |
||||
|
const sequelize = dc.orm; |
||||
|
const Department = sequelize.define("department", { |
||||
|
id: { |
||||
|
type: DataTypes.INTEGER, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: true, |
||||
|
field: "id", |
||||
|
autoIncrement: true, |
||||
|
unique: "department_id_uindex" |
||||
|
}, |
||||
|
name: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: false, |
||||
|
field: "name", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
dependence: { |
||||
|
type: DataTypes.INTEGER, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "上级部门/从属", |
||||
|
primaryKey: false, |
||||
|
field: "dependence", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
type: { |
||||
|
type: DataTypes.INTEGER, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "", |
||||
|
primaryKey: false, |
||||
|
field: "type", |
||||
|
autoIncrement: false |
||||
|
} |
||||
|
}, { |
||||
|
tableName: "department", |
||||
|
comment: "", |
||||
|
indexes: [] |
||||
|
}); |
||||
|
|
||||
|
dc.models.Department = Department; |
||||
|
|
||||
|
|
||||
|
|
||||
|
return Department; |
||||
|
}; |
@ -0,0 +1,105 @@ |
|||||
|
/* eslint-disable*/ |
||||
|
'use strict'; |
||||
|
|
||||
|
module.exports = dc => { |
||||
|
const DataTypes = dc.ORM; |
||||
|
const sequelize = dc.orm; |
||||
|
const PatrolPlan = sequelize.define("PatrolPlan", { |
||||
|
id: { |
||||
|
type: DataTypes.INTEGER, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: true, |
||||
|
field: "id", |
||||
|
autoIncrement: true, |
||||
|
unique: "patrol_plan_id_uindex" |
||||
|
}, |
||||
|
name: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: false, |
||||
|
field: "name", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
way: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: false, |
||||
|
field: "way", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
structureId: { |
||||
|
type: DataTypes.INTEGER, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: false, |
||||
|
field: "structure_id", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
startTime: { |
||||
|
type: DataTypes.DATE, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: false, |
||||
|
field: "start_time", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
endTime: { |
||||
|
type: DataTypes.DATE, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: false, |
||||
|
field: "end_time", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
frequency: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: false, |
||||
|
field: "frequency", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
points: { |
||||
|
type: DataTypes.JSONB, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: false, |
||||
|
field: "points", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
userId: { |
||||
|
type: DataTypes.INTEGER, |
||||
|
allowNull: true, |
||||
|
comment: null, |
||||
|
primaryKey: false, |
||||
|
field: "user_id", |
||||
|
autoIncrement: false, |
||||
|
}, |
||||
|
patrolCount: { |
||||
|
type: DataTypes.INTEGER, |
||||
|
allowNull: false, |
||||
|
defaultValue: 0, |
||||
|
comment: null, |
||||
|
primaryKey: false, |
||||
|
field: "patrol_count", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
}, { |
||||
|
tableName: "patrol_plan", |
||||
|
comment: "", |
||||
|
indexes: [] |
||||
|
}); |
||||
|
dc.models.PatrolPlan = PatrolPlan; |
||||
|
return PatrolPlan; |
||||
|
}; |
@ -0,0 +1,55 @@ |
|||||
|
/* eslint-disable*/ |
||||
|
'use strict'; |
||||
|
|
||||
|
module.exports = dc => { |
||||
|
const DataTypes = dc.ORM; |
||||
|
const sequelize = dc.orm; |
||||
|
const PatrolRecord = sequelize.define("PatrolRecord", { |
||||
|
id: { |
||||
|
field: "id", |
||||
|
type: DataTypes.INTEGER, |
||||
|
allowNull: false, |
||||
|
primaryKey: true, |
||||
|
autoIncrement: true, |
||||
|
}, |
||||
|
patrolPlanId: { |
||||
|
field: "patrol_plan_id", |
||||
|
type: DataTypes.INTEGER, |
||||
|
allowNull: false, |
||||
|
primaryKey: false, |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
lastInspectionTime: { |
||||
|
field: "last_inspection_time", |
||||
|
type: DataTypes.DATE, |
||||
|
allowNull: true, |
||||
|
}, |
||||
|
inspectionTime: { |
||||
|
field: "inspection_time", |
||||
|
type: DataTypes.DATE, |
||||
|
allowNull: true, |
||||
|
}, |
||||
|
points: { |
||||
|
field: "points", |
||||
|
type: DataTypes.JSONB, |
||||
|
allowNull: true, |
||||
|
}, |
||||
|
alarm: { |
||||
|
field: "alarm", |
||||
|
type: DataTypes.BOOLEAN, |
||||
|
allowNull: false, |
||||
|
defaultValue: false, |
||||
|
}, |
||||
|
pointId: { |
||||
|
field: "point_id", |
||||
|
type: DataTypes.INTEGER, |
||||
|
allowNull: false, |
||||
|
}, |
||||
|
}, { |
||||
|
tableName: "patrol_record", |
||||
|
comment: "", |
||||
|
indexes: [] |
||||
|
}); |
||||
|
dc.models.PatrolRecord = PatrolRecord; |
||||
|
return PatrolRecord; |
||||
|
}; |
@ -0,0 +1,79 @@ |
|||||
|
/* eslint-disable*/ |
||||
|
'use strict'; |
||||
|
|
||||
|
module.exports = dc => { |
||||
|
const DataTypes = dc.ORM; |
||||
|
const sequelize = dc.orm; |
||||
|
const Point = sequelize.define("point", { |
||||
|
id: { |
||||
|
type: DataTypes.INTEGER, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: true, |
||||
|
field: "id", |
||||
|
autoIncrement: true, |
||||
|
unique: "point_id_uindex" |
||||
|
}, |
||||
|
projectId: { |
||||
|
type: DataTypes.INTEGER, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: false, |
||||
|
field: "project_id", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
name: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: false, |
||||
|
field: "name", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
longitude: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: false, |
||||
|
field: "longitude", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
latitude: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: false, |
||||
|
field: "latitude", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
describe: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: false, |
||||
|
field: "describe", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
qrCode: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: false, |
||||
|
field: "qr_code", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
}, { |
||||
|
tableName: "point", |
||||
|
comment: "", |
||||
|
indexes: [] |
||||
|
}); |
||||
|
dc.models.Point = Point; |
||||
|
return Point; |
||||
|
}; |
@ -0,0 +1,97 @@ |
|||||
|
/* eslint-disable*/ |
||||
|
'use strict'; |
||||
|
|
||||
|
module.exports = dc => { |
||||
|
const DataTypes = dc.ORM; |
||||
|
const sequelize = dc.orm; |
||||
|
const Project = sequelize.define("project", { |
||||
|
id: { |
||||
|
type: DataTypes.INTEGER, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: true, |
||||
|
field: "id", |
||||
|
autoIncrement: true, |
||||
|
unique: "project_id_uindex" |
||||
|
}, |
||||
|
img: { |
||||
|
type: DataTypes.ARRAY(DataTypes.STRING), |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: false, |
||||
|
field: "img", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
userId: { |
||||
|
type: DataTypes.INTEGER, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: false, |
||||
|
field: "user_id", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
name: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: false, |
||||
|
field: "name", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
type: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: false, |
||||
|
field: "type", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
longitude: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: false, |
||||
|
field: "longitude", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
latitude: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: false, |
||||
|
field: "latitude", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
describe: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: false, |
||||
|
field: "describe", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
qrCode: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: false, |
||||
|
field: "qr_code", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
}, { |
||||
|
tableName: "project", |
||||
|
comment: "", |
||||
|
indexes: [] |
||||
|
}); |
||||
|
dc.models.Project = Project; |
||||
|
return Project; |
||||
|
}; |
@ -0,0 +1,44 @@ |
|||||
|
/* eslint-disable*/ |
||||
|
'use strict'; |
||||
|
|
||||
|
module.exports = dc => { |
||||
|
const DataTypes = dc.ORM; |
||||
|
const sequelize = dc.orm; |
||||
|
const Resource = sequelize.define("resource", { |
||||
|
code: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: true, |
||||
|
field: "code", |
||||
|
autoIncrement: false, |
||||
|
unique: "resource_code_uindex" |
||||
|
}, |
||||
|
name: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: false, |
||||
|
field: "name", |
||||
|
autoIncrement: false, |
||||
|
unique: "resource_name_uindex" |
||||
|
}, |
||||
|
parentResource: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: false, |
||||
|
field: "parent_resource", |
||||
|
autoIncrement: false |
||||
|
} |
||||
|
}, { |
||||
|
tableName: "resource", |
||||
|
comment: "", |
||||
|
indexes: [] |
||||
|
}); |
||||
|
dc.models.Resource = Resource; |
||||
|
return Resource; |
||||
|
}; |
@ -0,0 +1,107 @@ |
|||||
|
/* eslint-disable*/ |
||||
|
'use strict'; |
||||
|
|
||||
|
module.exports = dc => { |
||||
|
const DataTypes = dc.ORM; |
||||
|
const sequelize = dc.orm; |
||||
|
const User = sequelize.define("user", { |
||||
|
id: { |
||||
|
type: DataTypes.INTEGER, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: true, |
||||
|
field: "id", |
||||
|
autoIncrement: true, |
||||
|
unique: "user_id_uindex" |
||||
|
}, |
||||
|
name: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: false, |
||||
|
field: "name", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
username: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "用户名 账号", |
||||
|
primaryKey: false, |
||||
|
field: "username", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
password: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: false, |
||||
|
field: "password", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
departmentId: { |
||||
|
type: DataTypes.INTEGER, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "部门id", |
||||
|
primaryKey: false, |
||||
|
field: "department_id", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
email: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: false, |
||||
|
field: "email", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
enable: { |
||||
|
type: DataTypes.BOOLEAN, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "启用状态", |
||||
|
primaryKey: false, |
||||
|
field: "enable", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
delete: { |
||||
|
type: DataTypes.BOOLEAN, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: false, |
||||
|
field: "delete", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
phone: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "手机号(小程序使用手机号登录)", |
||||
|
primaryKey: false, |
||||
|
field: "phone", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
post: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "职位", |
||||
|
primaryKey: false, |
||||
|
field: "post", |
||||
|
autoIncrement: false |
||||
|
} |
||||
|
}, { |
||||
|
tableName: "user", |
||||
|
comment: "", |
||||
|
indexes: [] |
||||
|
}); |
||||
|
|
||||
|
dc.models.User = User; |
||||
|
return User; |
||||
|
}; |
@ -0,0 +1,52 @@ |
|||||
|
/* eslint-disable*/ |
||||
|
'use strict'; |
||||
|
|
||||
|
module.exports = dc => { |
||||
|
const DataTypes = dc.ORM; |
||||
|
const sequelize = dc.orm; |
||||
|
const UserResource = sequelize.define("userResource", { |
||||
|
id: { |
||||
|
type: DataTypes.INTEGER, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: true, |
||||
|
field: "id", |
||||
|
autoIncrement: true, |
||||
|
unique: "post_resource_id_uindex" |
||||
|
}, |
||||
|
userId: { |
||||
|
type: DataTypes.INTEGER, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: false, |
||||
|
field: "user_id", |
||||
|
autoIncrement: false, |
||||
|
references: { |
||||
|
key: "id", |
||||
|
model: "post" |
||||
|
} |
||||
|
}, |
||||
|
resourceId: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: false, |
||||
|
field: "resource", |
||||
|
autoIncrement: false, |
||||
|
references: { |
||||
|
key: "code", |
||||
|
model: "resource" |
||||
|
} |
||||
|
} |
||||
|
}, { |
||||
|
tableName: "user_resource", |
||||
|
comment: "", |
||||
|
indexes: [] |
||||
|
}); |
||||
|
|
||||
|
dc.models.UserResource = UserResource; |
||||
|
return UserResource; |
||||
|
}; |
@ -0,0 +1,43 @@ |
|||||
|
/* eslint-disable*/ |
||||
|
'use strict'; |
||||
|
|
||||
|
module.exports = dc => { |
||||
|
const DataTypes = dc.ORM; |
||||
|
const sequelize = dc.orm; |
||||
|
const UserToken = sequelize.define("userToken", { |
||||
|
token: { |
||||
|
type: DataTypes.UUIDV4, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: true, |
||||
|
field: "token", |
||||
|
autoIncrement: false, |
||||
|
unique: "user_token_token_uindex" |
||||
|
}, |
||||
|
userInfo: { |
||||
|
type: DataTypes.JSONB, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: false, |
||||
|
field: "user_info", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
expired: { |
||||
|
type: DataTypes.DATE, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: false, |
||||
|
field: "expired", |
||||
|
autoIncrement: false |
||||
|
} |
||||
|
}, { |
||||
|
tableName: "user_token", |
||||
|
comment: "", |
||||
|
indexes: [] |
||||
|
}); |
||||
|
dc.models.UserToken = UserToken; |
||||
|
return UserToken; |
||||
|
}; |
@ -0,0 +1,14 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
const auth = require('../../controllers/auth'); |
||||
|
|
||||
|
module.exports = function (app, router, opts) { |
||||
|
app.fs.api.logAttr['POST/login'] = { content: '登录', visible: true }; |
||||
|
router.post('/login', auth.login); |
||||
|
|
||||
|
app.fs.api.logAttr['POST/validate/phone'] = { content: '发送验证码', visible: true }; |
||||
|
router.post('/validate/phone', auth.varfiyCode); |
||||
|
|
||||
|
app.fs.api.logAttr['PUT/logout'] = { content: '登出', visible: false }; |
||||
|
router.put('/logout', auth.logout); |
||||
|
}; |
@ -0,0 +1,17 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
const path = require('path'); |
||||
|
const fs = require('fs'); |
||||
|
|
||||
|
module.exports = function (app, router, opts) { |
||||
|
fs.readdirSync(__dirname).forEach((filename) => { |
||||
|
if (filename.indexOf('.') !== 0 && fs.lstatSync(path.join(__dirname, filename)).isDirectory()) { |
||||
|
fs.readdirSync(path.join(__dirname, filename)).forEach((api) => { |
||||
|
if (api.indexOf('.') == 0 || api.indexOf('.js') == -1) return; |
||||
|
require(`./${filename}/${api}`)(app, router, opts); |
||||
|
}); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
return router; |
||||
|
}; |
@ -0,0 +1,28 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
const Authority = require('../../controllers/organization/authority'); |
||||
|
|
||||
|
module.exports = function (app, router, opts) { |
||||
|
/** |
||||
|
* @api {GET} resource 查询所有权限码. |
||||
|
* @apiVersion 1.0.0 |
||||
|
* @apiGroup Org |
||||
|
*/ |
||||
|
app.fs.api.logAttr['GET/resource'] = { content: '查询所有权限码', visible: true }; |
||||
|
router.get('resource', Authority.getResource); |
||||
|
/** |
||||
|
* @api {GET} user/resource 查询用户权限. |
||||
|
* @apiVersion 1.0.0 |
||||
|
* @apiGroup Org |
||||
|
*/ |
||||
|
app.fs.api.logAttr['GET/user/resource'] = { content: '查询用户权限', visible: true }; |
||||
|
router.get('user/resource', Authority.getUserResource); |
||||
|
|
||||
|
/** |
||||
|
* @api {POST} user/resource 更新用户权限. |
||||
|
* @apiVersion 1.0.0 |
||||
|
* @apiGroup Org |
||||
|
*/ |
||||
|
app.fs.api.logAttr['POST/user/resource'] = { content: '更新用户权限', visible: true }; |
||||
|
router.post('user/resource', Authority.updateUserRes); |
||||
|
}; |
@ -0,0 +1,41 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
const user = require('../../controllers/organization/user'); |
||||
|
|
||||
|
module.exports = function (app, router, opts) { |
||||
|
|
||||
|
app.fs.api.logAttr['GET/organization/department'] = { content: '获取部门信息', visible: false }; |
||||
|
router.get('/organization/department', user.getDepMessage); |
||||
|
|
||||
|
app.fs.api.logAttr['POST/organization/dept/add'] = { content: '新增部门', visible: true }; |
||||
|
router.post('/organization/dept/add', user.createDept); |
||||
|
|
||||
|
app.fs.api.logAttr['PUT/organization/dept/:id/modify'] = { content: '修改部门', visible: true }; |
||||
|
router.put('/organization/dept/:id/modify', user.updateDept); |
||||
|
|
||||
|
app.fs.api.logAttr['DELETE/organization/dept/:id'] = { content: '删除部门', visible: true }; |
||||
|
router.del('/organization/dept/:id', user.delDept); |
||||
|
|
||||
|
app.fs.api.logAttr['GET/organization/department/:depId/user'] = { content: '获取部门下用户信息', visible: false }; |
||||
|
router.get('/organization/department/:depId/user', user.getUser); |
||||
|
|
||||
|
app.fs.api.logAttr['POST/organization/department/user'] = { content: '创建部门下用户信息', visible: false }; |
||||
|
router.post('/organization/department/user', user.creatUser); |
||||
|
|
||||
|
app.fs.api.logAttr['PUT/organization/department/user/:id'] = { content: '修改部门下用户信息', visible: false }; |
||||
|
router.put('/organization/department/user/:id', user.updateUser); |
||||
|
|
||||
|
app.fs.api.logAttr['DEL/organization/department/user/:ids'] = { content: '删除部门下用户信息', visible: false }; |
||||
|
router.del('/organization/department/user/:ids', user.deleteUser); |
||||
|
|
||||
|
app.fs.api.logAttr['PUT/organization/department/user/resetPwd/:id'] = { content: '重置用户密码', visible: false }; |
||||
|
router.put('/organization/department/user/resetPwd/:id', user.resetPwd); |
||||
|
|
||||
|
/** |
||||
|
* @api {PUT} user/password/:id 修改用户密码 |
||||
|
* @apiVersion 1.0.0 |
||||
|
* @apiGroup Organization |
||||
|
*/ |
||||
|
app.fs.api.logAttr['PUT/user/password/:userId'] = { content: '修改用户密码', visible: false }; |
||||
|
router.put('/user/password/:userId', user.updateUserPassword); |
||||
|
}; |
@ -0,0 +1,17 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
const patrolPlan = require('../../controllers/patrolPlan/patrolPlan'); |
||||
|
|
||||
|
module.exports = function (app, router, opts) { |
||||
|
app.fs.api.logAttr['GET/patrolPlan'] = { content: '获取巡检计划', visible: false }; |
||||
|
router.get('/patrolPlan', patrolPlan.getPatrolPlan); |
||||
|
|
||||
|
app.fs.api.logAttr['POST/patrolPlan'] = { content: '新增巡检计划', visible: true }; |
||||
|
router.post('/patrolPlan', patrolPlan.createPatrolPlan); |
||||
|
|
||||
|
app.fs.api.logAttr['PUT/patrolPlan'] = { content: '修改巡检计划', visible: true }; |
||||
|
router.put('/patrolPlan', patrolPlan.updatePatrolPlan); |
||||
|
|
||||
|
app.fs.api.logAttr['DELETE/patrolPlan/:id'] = { content: '删除巡检计划', visible: true }; |
||||
|
router.del('/patrolPlan/:id', patrolPlan.delPatrolPlan); |
||||
|
}; |
@ -0,0 +1,12 @@ |
|||||
|
'use strict'; |
||||
|
const patrolRecord = require('../../controllers/patrolRecord/patrolRecord'); |
||||
|
|
||||
|
module.exports = function (app, router, opts) { |
||||
|
app.fs.api.logAttr['GET/patrolRecord/:patrolPlanId/:startTime/:endTime/:alarm/:pointId'] = { content: '获取巡检记录', visible: true }; |
||||
|
// web端、小程序端查数据:patrolPlanId为all,不需要传pointId
|
||||
|
// 小程序端查点位最新一条数据:startTime、endTime、alarm不传
|
||||
|
router.get('/patrolRecord/:patrolPlanId/:startTime/:endTime/:alarm/:pointId', patrolRecord.findPatrolRecord); |
||||
|
|
||||
|
app.fs.api.logAttr['POST/patrolRecord/add'] = { content: '新增巡检记录', visible: true } |
||||
|
router.post('/patrolRecord/add', patrolRecord.addPatrolRecord); |
||||
|
}; |
@ -0,0 +1,31 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
const projectSituation = require('../../controllers/projectRegime/projectSituation'); |
||||
|
|
||||
|
module.exports = function (app, router, opts) { |
||||
|
|
||||
|
app.fs.api.logAttr['GET/projectList'] = { content: '获取结构物列表', visible: false }; |
||||
|
router.get('/projectList', projectSituation.projectList); |
||||
|
|
||||
|
app.fs.api.logAttr['POST/addProject'] = { content: '新增修改结构物', visible: false }; |
||||
|
router.post('/addProject', projectSituation.postAddProject); |
||||
|
|
||||
|
app.fs.api.logAttr['DEL/delProject/:id'] = { content: '删除结构物', visible: false }; |
||||
|
router.del('/delProject/:id', projectSituation.delProject); |
||||
|
|
||||
|
app.fs.api.logAttr['POST/position'] = { content: '新增修改点位', visible: false }; |
||||
|
router.post('/position', projectSituation.addPosition); |
||||
|
|
||||
|
app.fs.api.logAttr['GET/position'] = { content: '获取点位列表', visible: false }; |
||||
|
router.get('/position', projectSituation.position); |
||||
|
|
||||
|
app.fs.api.logAttr['DEL/delPosition/:id'] = { content: '删除点位', visible: false }; |
||||
|
router.del('/delPosition/:id', projectSituation.delPosition); |
||||
|
|
||||
|
app.fs.api.logAttr['GET/qrCodeShow'] = { content: '获取二维码列表', visible: false }; |
||||
|
router.get('/qrCodeShow', projectSituation.qrCodeShow); |
||||
|
|
||||
|
app.fs.api.logAttr['GET/q'] = { content: '获取二维码列表', visible: false }; |
||||
|
router.get('/q', projectSituation.q); |
||||
|
|
||||
|
} |
@ -0,0 +1,53 @@ |
|||||
|
const moment = require('moment') |
||||
|
const rimraf = require('rimraf'); |
||||
|
const fs = require("fs"); |
||||
|
const path = require("path") |
||||
|
|
||||
|
let TEST = false |
||||
|
// TEST = true
|
||||
|
|
||||
|
module.exports = function (app, opts) { |
||||
|
const clearExpiredData = app.fs.scheduleInit( |
||||
|
{ |
||||
|
interval: '42 24 4 */3 * *', |
||||
|
immediate: TEST, |
||||
|
proRun: !TEST, |
||||
|
}, |
||||
|
async () => { |
||||
|
try { |
||||
|
const { models } = app.fs.dc |
||||
|
const now = moment().format('YYYY-MM-DD HH:mm:ss') |
||||
|
await models.UserToken.destroy({ |
||||
|
where: { |
||||
|
expired: { $lt: now } |
||||
|
} |
||||
|
}) |
||||
|
await models.PhoneValidateCode.destroy({ |
||||
|
where: { |
||||
|
expired: { $lt: now } |
||||
|
} |
||||
|
}) |
||||
|
fs.readdir(path.join(__dirname, `../../downloadFiles`), function (err, files) { |
||||
|
if (err) { |
||||
|
return; |
||||
|
} |
||||
|
files.forEach((file) => { |
||||
|
fs.stat(path.join(__dirname, `../../downloadFiles/${file}`), (err, stats) => { |
||||
|
if (err) { |
||||
|
//return;
|
||||
|
} else { |
||||
|
rimraf.sync(path.join(__dirname, `../../downloadFiles/${file}`)); |
||||
|
} |
||||
|
}); |
||||
|
}); |
||||
|
}); |
||||
|
} catch (error) { |
||||
|
app.fs.logger.error(`sechedule: clearExpiredToken, error: ${error}`); |
||||
|
} |
||||
|
} |
||||
|
); |
||||
|
|
||||
|
return { |
||||
|
clearExpiredData |
||||
|
} |
||||
|
} |
@ -0,0 +1,208 @@ |
|||||
|
const fs = require('fs'); |
||||
|
const moment = require('moment') |
||||
|
const path = require('path') |
||||
|
const OSS = require('ali-oss'); |
||||
|
const uuid = require('uuid'); |
||||
|
|
||||
|
const TEST = false |
||||
|
// const TEST = true
|
||||
|
|
||||
|
module.exports = function (app, opts) { |
||||
|
const hideDangerStatistic = app.fs.scheduleInit( |
||||
|
// 按月、季度、年统计隐患整改
|
||||
|
{ |
||||
|
interval: '0 32 4 1 */1 *', |
||||
|
immediate: TEST, |
||||
|
proRun: !TEST, |
||||
|
}, |
||||
|
async () => { |
||||
|
const { aliOss } = opts |
||||
|
const { utils: { simpleExcelDown } } = app.fs; |
||||
|
|
||||
|
try { |
||||
|
const { models } = app.fs.dc |
||||
|
const today = moment() |
||||
|
const date = today.date() |
||||
|
const month = today.month() + 1 |
||||
|
const quarter = today.quarter() |
||||
|
const year = today.year() |
||||
|
|
||||
|
const client = new OSS({ |
||||
|
// yourRegion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
|
||||
|
region: aliOss.region, |
||||
|
// 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
|
||||
|
accessKeyId: aliOss.accessKey, |
||||
|
accessKeySecret: aliOss.secretKey, |
||||
|
// 填写Bucket名称,例如examplebucket。
|
||||
|
bucket: aliOss.bucket, |
||||
|
}); |
||||
|
|
||||
|
|
||||
|
const statistic = async (startTime, endTime, type, timeShow, typeEnglish, time) => { |
||||
|
const siteRectifyRes = await models.HideDangerRectifySites.findAll({ |
||||
|
where: {}, |
||||
|
distinct: true, |
||||
|
include: [{ |
||||
|
model: models.Site, |
||||
|
attributes: ['id', 'name'], |
||||
|
}, { |
||||
|
model: models.HideDangerDispose, |
||||
|
order: [['id', 'ASC']], |
||||
|
// include: [{
|
||||
|
// model: models.User,
|
||||
|
// attributes: ['id', 'displayName'],
|
||||
|
// }]
|
||||
|
}, { |
||||
|
model: models.HideDangerRectify, |
||||
|
where: { |
||||
|
createTime: { |
||||
|
$between: [ |
||||
|
startTime.format('YYYY-MM-DD HH:mm:ss'), |
||||
|
endTime.format('YYYY-MM-DD HH:mm:ss') |
||||
|
] |
||||
|
} |
||||
|
}, |
||||
|
},] |
||||
|
}) |
||||
|
|
||||
|
let reportHeader = [{ |
||||
|
title: "工程项目名称", |
||||
|
key: "siteName", |
||||
|
}, { |
||||
|
title: "整改任务名称", |
||||
|
key: "name", |
||||
|
}, { |
||||
|
title: "提交时间", |
||||
|
key: "submitTime", |
||||
|
}, { |
||||
|
title: "审批状态", |
||||
|
key: "state", |
||||
|
},] |
||||
|
let reportData = [] |
||||
|
|
||||
|
let siteMap = new Set() |
||||
|
let completedRectifyCount = 0 |
||||
|
let uncompletedRectifyCount = 0 |
||||
|
for (let s of siteRectifyRes) { |
||||
|
siteMap.add(s.siteId); |
||||
|
|
||||
|
let sts = s.status |
||||
|
let stsChinese = '' |
||||
|
if (sts == 0) { |
||||
|
stsChinese = '待整改' |
||||
|
} else if (sts == 1) { |
||||
|
stsChinese = '待审批' |
||||
|
} else if (sts == 2) { |
||||
|
stsChinese = '待复审' |
||||
|
} else if (sts == 3 || sts == 4) { |
||||
|
stsChinese = '审批驳回' |
||||
|
} else if (sts == 5) { |
||||
|
stsChinese = '审批通过' |
||||
|
} |
||||
|
|
||||
|
if ( |
||||
|
s.hideDangerDisposes.length |
||||
|
&& s.hideDangerDisposes.some(sd => sd.type == 3 && sd.admit) |
||||
|
) { |
||||
|
completedRectifyCount++ |
||||
|
} else { |
||||
|
uncompletedRectifyCount++ |
||||
|
} |
||||
|
|
||||
|
reportData.push({ |
||||
|
siteName: s.dataValues.site.dataValues.name, |
||||
|
name: s.dataValues.hideDangerRectify.dataValues.name, |
||||
|
submitTime: s.dataValues.lastDisposeTime ? moment(s.dataValues.lastDisposeTime).format('YYYY-MM-DD HH:mm:ss') : '', |
||||
|
state: stsChinese |
||||
|
}) |
||||
|
} |
||||
|
const fileName = `中鼎国际隐患整改数据报表-${type}-${timeShow}` + '.xlsx' |
||||
|
const filePath = await simpleExcelDown({ |
||||
|
data: reportData, header: reportHeader, fileName |
||||
|
}) |
||||
|
// const fileData = fs.readFileSync(filePath);
|
||||
|
|
||||
|
// 保存文件到云
|
||||
|
|
||||
|
let uploadPath = path.posix.join('hideDangerReport', uuid.v4(), fileName); |
||||
|
let uploadResult = await client.put( |
||||
|
uploadPath, |
||||
|
filePath, |
||||
|
// { contentLength: size }
|
||||
|
); |
||||
|
//保存信息到数据库
|
||||
|
const existReportRes = await models.HideDangerReport.findOne({ |
||||
|
where: { |
||||
|
type: typeEnglish, |
||||
|
time: String(time), |
||||
|
} |
||||
|
}) |
||||
|
const storageData = { |
||||
|
siteCount: siteMap.size, |
||||
|
rectifyCount: completedRectifyCount + uncompletedRectifyCount, |
||||
|
completedRectifyCount, |
||||
|
uncompletedRectifyCount, |
||||
|
report: uploadResult.name, |
||||
|
type: typeEnglish, |
||||
|
time: String(time), |
||||
|
} |
||||
|
if (existReportRes) { |
||||
|
await models.HideDangerReport.update(storageData, { |
||||
|
where: { |
||||
|
id: existReportRes.id |
||||
|
} |
||||
|
}) |
||||
|
} else { |
||||
|
await models.HideDangerReport.create(storageData) |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
if (month == 1) { |
||||
|
// 统计一下上一年
|
||||
|
let startTime = today.clone().subtract(1, 'year').startOf('year') |
||||
|
let endTime = today.clone().subtract(1, 'year').endOf('year') |
||||
|
await statistic( |
||||
|
startTime, |
||||
|
endTime, |
||||
|
'年报', |
||||
|
`${startTime.year()}${startTime.month() + 1}-${endTime.month() + 1}`, |
||||
|
'year', |
||||
|
startTime.year() |
||||
|
) |
||||
|
} |
||||
|
if ([1, 4, 7, 10].includes(month)) { |
||||
|
// 统计一下上季度
|
||||
|
let startTime = today.clone().subtract(3, 'month').startOf('month') |
||||
|
let endTime = today.clone().subtract(1, 'month').endOf('month') |
||||
|
await statistic( |
||||
|
startTime, |
||||
|
endTime, |
||||
|
'季报', |
||||
|
`${startTime.year()}${startTime.month() + 1}-${endTime.month() + 1}`, |
||||
|
'quarter', |
||||
|
`${startTime.year()}-${month == 1 ? 'Q4' : month == 4 ? 'Q1' : month == 7 ? 'Q2' : 'Q3'}` |
||||
|
) |
||||
|
} |
||||
|
// 统计一下上个月
|
||||
|
let startTime = today.clone().subtract(1, 'month').startOf('month') |
||||
|
let endTime = today.clone().subtract(1, 'month').endOf('month') |
||||
|
await statistic( |
||||
|
startTime, |
||||
|
endTime, |
||||
|
'月报', |
||||
|
`${startTime.year()}${startTime.month() + 1}`, |
||||
|
'month', |
||||
|
startTime.format('YYYY-MM') |
||||
|
) |
||||
|
|
||||
|
} catch (error) { |
||||
|
app.fs.logger.error(`sechedule: hideDangerStatistic, error: ${error}`); |
||||
|
} |
||||
|
} |
||||
|
); |
||||
|
|
||||
|
return { |
||||
|
hideDangerStatistic |
||||
|
} |
||||
|
} |
@ -0,0 +1,36 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
const fs = require('fs'); |
||||
|
const nodeSchedule = require('node-schedule'); |
||||
|
|
||||
|
// 将定时任务汇集未来可根据需要选取操作
|
||||
|
module.exports = async function (app, opts) { |
||||
|
|
||||
|
const scheduleInit = ({ |
||||
|
interval, immediate, proRun, |
||||
|
}, callback) => { |
||||
|
if (proRun && opts.dev) { |
||||
|
return; |
||||
|
} |
||||
|
const j = nodeSchedule.scheduleJob(interval, callback); |
||||
|
if (immediate && (!proRun || (proRun && !opts.dev))) { |
||||
|
setTimeout(callback, 0) |
||||
|
} |
||||
|
return j; |
||||
|
} |
||||
|
|
||||
|
app.fs.scheduleInit = scheduleInit |
||||
|
|
||||
|
fs.readdirSync(__dirname).forEach((filename) => { |
||||
|
if (!['index.js'].some(f => filename == f)) { |
||||
|
const scheduleList = require(`./${filename}`)(app, opts) |
||||
|
for (let k of Object.keys(scheduleList)) { |
||||
|
console.info(`定时任务 ${k} 启动`); |
||||
|
} |
||||
|
app.fs.schedule = { |
||||
|
...app.fs.schedule, |
||||
|
...scheduleList, |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
|
}; |
@ -0,0 +1,64 @@ |
|||||
|
const moment = require('moment') |
||||
|
|
||||
|
const TEST = false |
||||
|
// const TEST = true
|
||||
|
|
||||
|
module.exports = function (app, opts) { |
||||
|
const mettingGenerate = app.fs.scheduleInit( |
||||
|
{ |
||||
|
interval: '0 0 0 */1 * *', |
||||
|
immediate: TEST, |
||||
|
proRun: !TEST, |
||||
|
}, |
||||
|
async () => { |
||||
|
try { |
||||
|
const { models } = app.fs.dc |
||||
|
const today = moment() |
||||
|
const date = today.date() |
||||
|
const dateFormat = moment().format('YYYY-MM-DD') |
||||
|
let sites = await models.Site.findAll({ |
||||
|
where: { del: false }, |
||||
|
attributes: ['id', 'name'] |
||||
|
}); |
||||
|
let datasM = [], datasB = [], datasD = [], datas6 = [] |
||||
|
sites.map(s => { |
||||
|
datasM.push({ |
||||
|
siteId: s.id, |
||||
|
type: '月度安全例会', |
||||
|
date: dateFormat |
||||
|
}); |
||||
|
datasB.push({ |
||||
|
siteId: s.id, |
||||
|
type: '班前会', |
||||
|
date: dateFormat |
||||
|
}); |
||||
|
datasD.push({ |
||||
|
siteId: s.id, |
||||
|
type: '日调度会', |
||||
|
date: dateFormat |
||||
|
}); |
||||
|
datas6.push({ |
||||
|
siteId: s.id, |
||||
|
type: '逢六教育培训', |
||||
|
date: dateFormat |
||||
|
}) |
||||
|
}) |
||||
|
if (date == 1) { |
||||
|
await models.Metting.bulkCreate(datasM) |
||||
|
} |
||||
|
await models.Metting.bulkCreate(datasB) |
||||
|
await models.Metting.bulkCreate(datasD) |
||||
|
if (parseInt(date) % 10 == 6) { |
||||
|
await models.Metting.bulkCreate(datas6) |
||||
|
} |
||||
|
|
||||
|
} catch (error) { |
||||
|
app.fs.logger.error(`sechedule: mettingGenerate, error: ${error}`); |
||||
|
} |
||||
|
} |
||||
|
); |
||||
|
|
||||
|
return { |
||||
|
mettingGenerate |
||||
|
} |
||||
|
} |
@ -0,0 +1,36 @@ |
|||||
|
'use strict'; |
||||
|
const { ClickHouse } = require('clickhouse'); |
||||
|
|
||||
|
function factory (app, opts) { |
||||
|
if (opts.clickHouse) { |
||||
|
try { |
||||
|
app.fs.clickHouse = {} |
||||
|
const { url, port, user, password, db = [] } = opts.clickHouse |
||||
|
for (let d of db) { |
||||
|
if (d.name && d.db) { |
||||
|
app.fs.clickHouse[d.name] = new ClickHouse({ |
||||
|
url: url, |
||||
|
port: port, |
||||
|
debug: opts.dev, |
||||
|
format: "json", |
||||
|
basicAuth: user && password ? { |
||||
|
username: user, |
||||
|
password: password, |
||||
|
} : null, |
||||
|
config: { |
||||
|
database: d.db, |
||||
|
}, |
||||
|
}) |
||||
|
console.info(`ClickHouse ${d.name} 初始化完成`); |
||||
|
} else { |
||||
|
throw 'opts.clickHouse 参数错误!' |
||||
|
} |
||||
|
} |
||||
|
} catch (error) { |
||||
|
console.error(error) |
||||
|
process.exit(-1); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
module.exports = factory; |
@ -0,0 +1,67 @@ |
|||||
|
'use strict'; |
||||
|
const request = require('superagent') |
||||
|
|
||||
|
class paasRequest { |
||||
|
constructor(root, { query = {} } = {}, option) { |
||||
|
this.root = root; |
||||
|
this.query = query |
||||
|
this.option = option |
||||
|
} |
||||
|
|
||||
|
#buildUrl = (url) => { |
||||
|
return `${this.root}/${url}`; |
||||
|
} |
||||
|
|
||||
|
#resultHandler = (resolve, reject) => { |
||||
|
return (err, res) => { |
||||
|
if (err) { |
||||
|
reject(err); |
||||
|
} else { |
||||
|
resolve(res[this.option.dataWord]); |
||||
|
} |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
get = (url, { query = {}, header = {} } = {}) => { |
||||
|
return new Promise((resolve, reject) => { |
||||
|
request.get(this.#buildUrl(url)).set(header).query(Object.assign(query, this.query)).end(this.#resultHandler(resolve, reject)); |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
post = (url, { data = {}, query = {}, header = {} } = {}) => { |
||||
|
return new Promise((resolve, reject) => { |
||||
|
request.post(this.#buildUrl(url)).set(header).query(Object.assign(query, this.query)).send(data).end(this.#resultHandler(resolve, reject)); |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
put = (url, { data = {}, header = {}, query = {}, } = {}) => { |
||||
|
return new Promise((resolve, reject) => { |
||||
|
request.put(this.#buildUrl(url)).set(header).query(Object.assign(query, this.query)).send(data).end(this.#resultHandler(resolve, reject)); |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
delete = (url, { header = {}, query = {} } = {}) => { |
||||
|
return new Promise((resolve, reject) => { |
||||
|
request.delete(this.#buildUrl(url)).set(header).query(Object.assign(query, this.query)).end(this.#resultHandler(resolve, reject)); |
||||
|
}) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
function factory (app, opts) { |
||||
|
if (opts.pssaRequest) { |
||||
|
try { |
||||
|
for (let r of opts.pssaRequest) { |
||||
|
if (r.name && r.root) { |
||||
|
app.fs[r.name] = new paasRequest(r.root, { ...(r.params || {}) }, { dataWord: r.dataWord || 'body' }) |
||||
|
} else { |
||||
|
throw 'opts.pssaRequest 参数错误!' |
||||
|
} |
||||
|
} |
||||
|
} catch (error) { |
||||
|
console.error(error) |
||||
|
process.exit(-1); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
module.exports = factory; |
@ -0,0 +1,41 @@ |
|||||
|
'use strict'; |
||||
|
// https://github.com/luin/ioredis
|
||||
|
const redis = require("ioredis") |
||||
|
|
||||
|
module.exports = async function factory (app, opts) { |
||||
|
let client = opts.redis.pwd ? |
||||
|
new redis.Cluster([ |
||||
|
{ |
||||
|
host: opts.redis.host, |
||||
|
port: opts.redis.port |
||||
|
} |
||||
|
], { |
||||
|
redisOptions: { |
||||
|
password: opts.redis.pwd, |
||||
|
}, |
||||
|
}) |
||||
|
: new redis(opts.redis.port, opts.redis.host, { |
||||
|
password: opts.redis.pwd, |
||||
|
}); |
||||
|
|
||||
|
client.on("error", function (err) { |
||||
|
app.fs.logger.error('info', '[FS-AUTH-REDIS]', `redis connect error. ${opts.redis.host + ':' + opts.redis.port}`); |
||||
|
// console.error("Error :", err);
|
||||
|
// process.exit(-1);
|
||||
|
}); |
||||
|
|
||||
|
client.on('connect', function () { |
||||
|
console.info(`redis connect success ${opts.redis.host + ':' + opts.redis.port}`); |
||||
|
}) |
||||
|
|
||||
|
// 自定义方法
|
||||
|
async function hdelall (key) { |
||||
|
const obj = await client.hgetall(key); |
||||
|
await client.hdel(key, Object.keys(obj)) |
||||
|
} |
||||
|
|
||||
|
app.redis = client |
||||
|
app.redisTools = { |
||||
|
hdelall, |
||||
|
} |
||||
|
} |
@ -0,0 +1,31 @@ |
|||||
|
'use strict'; |
||||
|
const moment = require('moment') |
||||
|
|
||||
|
module.exports = async function factory (app, opts) { |
||||
|
|
||||
|
app.socket.on('connection', async (socket) => { |
||||
|
console.info('WEB_SOCKET token:' + socket.handshake.query.token + ' 已连接:id ' + socket.id + ' 时间:' + moment(socket.handshake.time).format()); |
||||
|
|
||||
|
socket.on('disconnecting', async (reason) => { |
||||
|
const connectSeconds = moment().diff(moment(socket.handshake.time), 'seconds') |
||||
|
|
||||
|
console.info('WEB_SOCKET token:' + socket.handshake.query.token + ' 已断开连接:' + reason + ' 连接时长:' + connectSeconds + 's'); |
||||
|
}) |
||||
|
}) |
||||
|
|
||||
|
// 使用测试 保持链接
|
||||
|
// setInterval(async () => {
|
||||
|
// const { connected } = app.socket.sockets
|
||||
|
|
||||
|
// const roomId = 'ROOM_' + Math.random()
|
||||
|
// // if (connected) {
|
||||
|
// // for (let c in connected) {
|
||||
|
// // connected[c].join(roomId)
|
||||
|
// // }
|
||||
|
// // app.socket.to(roomId).emit('TEST', { someProperty: `【星域 ROOM:${roomId}】呼叫自然选择号!!!`, })
|
||||
|
// // }
|
||||
|
|
||||
|
// app.socket.emit('TEST', { someProperty: '【广播】呼叫青铜时代号!!!', })
|
||||
|
|
||||
|
// }, 3000)
|
||||
|
} |
@ -0,0 +1,17 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
const path = require('path'); |
||||
|
const fs = require('fs'); |
||||
|
|
||||
|
module.exports = async function (app, opts) { |
||||
|
fs.readdirSync(__dirname).forEach((filename) => { |
||||
|
if (!['index.js'].some(f => filename == f)) { |
||||
|
const utils = require(`./${filename}`)(app, opts) |
||||
|
console.log(`载入 ${filename} 工具集成功`); |
||||
|
app.fs.utils = { |
||||
|
...app.fs.utils, |
||||
|
...utils, |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
|
}; |
@ -0,0 +1,415 @@ |
|||||
|
'use strict'; |
||||
|
const moment = require('moment') |
||||
|
const request = require('superagent'); |
||||
|
|
||||
|
module.exports = function (app, opts) { |
||||
|
|
||||
|
async function memberList ({ |
||||
|
keywordTarget, keyword, limit, page, state, |
||||
|
hiredateStart, hiredateEnd, marital, native, workPlace, |
||||
|
orderBy, orderDirection, |
||||
|
nowAttendanceTime, |
||||
|
overtimeDayStatisticStartDate, overtimeDayStatisticendDate, |
||||
|
overtimeCountStatistic, overtimeCountStatisticStartDate, overtimeCountStatisticendDate, |
||||
|
vacateDayStatisticStartDate, vacateDayStatisticendDate, |
||||
|
vacateDurationStatistic, vacateCountStatistic, vacateCountStatisticStartDate, vacateCountStatisticendDate |
||||
|
}) { |
||||
|
const { judgeHoliday } = app.fs.utils |
||||
|
const { clickHouse } = app.fs |
||||
|
const { database: pepEmis } = clickHouse.pepEmis.opts.config |
||||
|
|
||||
|
const curDay = moment().format('YYYY-MM-DD') |
||||
|
const nowTime = moment() |
||||
|
let whereOption = [] |
||||
|
let whereFromSelectOption = [] |
||||
|
let returnEmpty = false |
||||
|
if (state == 'inOffice') { |
||||
|
// 在岗
|
||||
|
const holidayJudge = await judgeHoliday(curDay) |
||||
|
if (holidayJudge) { |
||||
|
if ( |
||||
|
holidayJudge.workday |
||||
|
&& nowTime.isAfter(moment(curDay + ' 08:30')) |
||||
|
&& nowTime.isBefore(moment(curDay + ' 17:30')) |
||||
|
) { |
||||
|
// 在工作日的工作时间范围 无请假记录
|
||||
|
whereFromSelectOption.push(`vacateStartTime = '1970-01-01 00:00:00.000000'`) |
||||
|
} else { |
||||
|
returnEmpty = true |
||||
|
} |
||||
|
} else { |
||||
|
returnEmpty = true |
||||
|
} |
||||
|
} |
||||
|
if (state == 'dayoff') { |
||||
|
// 放假
|
||||
|
const holidayJudge = await judgeHoliday(curDay) |
||||
|
if (holidayJudge) { |
||||
|
if ( |
||||
|
holidayJudge.dayoff || holidayJudge.festivals |
||||
|
) { |
||||
|
// 在休息日范围内且无加班申请
|
||||
|
whereFromSelectOption.push(`overtimeStartTime = '1970-01-01 00:00:00.000000'`) |
||||
|
} else { |
||||
|
returnEmpty = true |
||||
|
} |
||||
|
} else { |
||||
|
returnEmpty = true |
||||
|
} |
||||
|
} |
||||
|
if (returnEmpty) { |
||||
|
return { |
||||
|
count: 0, |
||||
|
rows: [] |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
let overtimeDayStatisticWhere = [] |
||||
|
if (overtimeDayStatisticStartDate) { |
||||
|
overtimeDayStatisticWhere.push(`overtime_day.day >= '${moment(overtimeDayStatisticStartDate).format('YYYY-MM-DD')}'`) |
||||
|
} |
||||
|
if (overtimeDayStatisticendDate) { |
||||
|
overtimeDayStatisticWhere.push(`overtime_day.day <= '${moment(overtimeDayStatisticendDate).format('YYYY-MM-DD')}'`) |
||||
|
} |
||||
|
|
||||
|
let overtimeCountStatisticWhere = [] |
||||
|
if (overtimeCountStatisticStartDate) { |
||||
|
overtimeCountStatisticWhere.push(`overtime.start_time >= '${moment(overtimeCountStatisticStartDate).startOf('day').format('YYYY-MM-DD HH:mm:ss')}'`) |
||||
|
} |
||||
|
if (overtimeCountStatisticendDate) { |
||||
|
overtimeCountStatisticWhere.push(`overtime.end_time <= '${moment(overtimeCountStatisticendDate).endOf('day').format('YYYY-MM-DD HH:mm:ss')}'`) |
||||
|
} |
||||
|
|
||||
|
let vacateDayStatisticWhere = [] |
||||
|
if (vacateDayStatisticStartDate) { |
||||
|
vacateDayStatisticWhere.push(`vacate_day.day >= '${moment(vacateDayStatisticStartDate).format('YYYY-MM-DD')}'`) |
||||
|
} |
||||
|
if (vacateDayStatisticendDate) { |
||||
|
vacateDayStatisticWhere.push(`vacate_day.day <= '${moment(vacateDayStatisticendDate).format('YYYY-MM-DD')}'`) |
||||
|
} |
||||
|
|
||||
|
let vacateCountStatisticWhere = [] |
||||
|
if (vacateCountStatisticStartDate) { |
||||
|
vacateCountStatisticWhere.push(`vacate.start_time >= '${moment(vacateCountStatisticStartDate).startOf('day').format('YYYY-MM-DD HH:mm:ss')}'`) |
||||
|
} |
||||
|
if (vacateCountStatisticendDate) { |
||||
|
vacateCountStatisticWhere.push(`vacate.end_time <= '${moment(vacateCountStatisticendDate).endOf('day').format('YYYY-MM-DD HH:mm:ss')}'`) |
||||
|
} |
||||
|
// CRAZY
|
||||
|
const innerSelectQuery = ` |
||||
|
FROM member |
||||
|
INNER JOIN ${pepEmis}.user AS user |
||||
|
ON member.pep_user_id = user.id |
||||
|
${keywordTarget == 'number' && keyword ? ` |
||||
|
AND user.people_code LIKE '%${keyword}%' |
||||
|
`: ''}
|
||||
|
${keywordTarget == 'name' && keyword ? ` |
||||
|
AND user.name LIKE '%${keyword}%' |
||||
|
`: ''}
|
||||
|
|
||||
|
${nowAttendanceTime ? ` |
||||
|
${state == 'vacate' ? 'INNER' : 'LEFT'} JOIN ( |
||||
|
SELECT |
||||
|
pep_user_id, |
||||
|
any(start_time) AS vacateStartTime, |
||||
|
any(end_time) AS vacateEndTime |
||||
|
FROM vacate |
||||
|
WHERE |
||||
|
start_time <= '${nowTime.format('YYYY-MM-DD HH:mm:ss')}' |
||||
|
AND end_time > '${nowTime.format('YYYY-MM-DD HH:mm:ss')}' |
||||
|
GROUP BY pep_user_id |
||||
|
) AS hrVacate |
||||
|
ON hrVacate.pep_user_id = member.pep_user_id |
||||
|
`: ''}
|
||||
|
${nowAttendanceTime ? ` |
||||
|
LEFT JOIN ( |
||||
|
SELECT |
||||
|
pep_user_id, |
||||
|
any(start_time) AS overtimeStartTime, |
||||
|
any(end_time) AS overtimeEndTime |
||||
|
FROM overtime |
||||
|
WHERE |
||||
|
start_time <= '${nowTime.format('YYYY-MM-DD HH:mm:ss')}' |
||||
|
AND end_time > '${nowTime.format('YYYY-MM-DD HH:mm:ss')}' |
||||
|
GROUP BY pep_user_id |
||||
|
) AS hrOvertime |
||||
|
ON hrOvertime.pep_user_id = member.pep_user_id |
||||
|
`: ''}
|
||||
|
|
||||
|
${orderBy == 'overtimeTakeRestSum' || |
||||
|
orderBy == 'overtimePaySum' || |
||||
|
orderBy == 'overtimeSum' ? |
||||
|
`LEFT JOIN (
|
||||
|
SELECT |
||||
|
overtime.pep_user_id AS pepUserId, |
||||
|
sum(overtime_day.duration) AS duration |
||||
|
FROM overtime_day |
||||
|
INNER JOIN overtime |
||||
|
ON overtime.id = overtime_day.overtime_id |
||||
|
${orderBy == 'overtimeTakeRestSum' ? `AND overtime.compensate = '调休'` : ''} |
||||
|
${orderBy == 'overtimePaySum' ? `AND overtime.compensate = '发放加班补偿'` : ''} |
||||
|
${overtimeDayStatisticWhere.length ? ` |
||||
|
WHERE ${overtimeDayStatisticWhere.join(' AND ')} |
||||
|
`: ''}
|
||||
|
GROUP BY overtime.pep_user_id |
||||
|
) AS overtimeDayStatistic |
||||
|
ON overtimeDayStatistic.pepUserId = member.pep_user_id`: ''}
|
||||
|
|
||||
|
${overtimeCountStatistic ? ` |
||||
|
LEFT JOIN ( |
||||
|
SELECT |
||||
|
overtime.pep_user_id AS pepUserId, |
||||
|
count(pep_process_story_id) AS count |
||||
|
FROM overtime |
||||
|
${overtimeCountStatisticWhere.length ? ` |
||||
|
WHERE ${overtimeCountStatisticWhere.join(' AND ')} |
||||
|
`: ''}
|
||||
|
GROUP BY overtime.pep_user_id |
||||
|
) AS overtimeCountStatistic |
||||
|
ON overtimeCountStatistic.pepUserId = member.pep_user_id |
||||
|
`: ''}
|
||||
|
|
||||
|
${vacateDurationStatistic || |
||||
|
orderBy == 'vacateSum' ? |
||||
|
`LEFT JOIN (
|
||||
|
SELECT |
||||
|
vacate.pep_user_id AS pepUserId, |
||||
|
sum(vacate_day.duration) AS duration |
||||
|
FROM vacate_day |
||||
|
INNER JOIN vacate |
||||
|
ON vacate.id = vacate_day.vacate_id |
||||
|
${vacateDayStatisticWhere.length ? ` |
||||
|
WHERE ${vacateDayStatisticWhere.join(' AND ')} |
||||
|
`: ''}
|
||||
|
GROUP BY vacate.pep_user_id |
||||
|
) AS vacateDayStatistic |
||||
|
ON vacateDayStatistic.pepUserId = member.pep_user_id`: ''}
|
||||
|
|
||||
|
${vacateCountStatistic ? ` |
||||
|
LEFT JOIN ( |
||||
|
SELECT |
||||
|
vacate.pep_user_id AS pepUserId, |
||||
|
count(pep_process_story_id) AS count |
||||
|
FROM vacate |
||||
|
${vacateCountStatisticWhere.length ? ` |
||||
|
WHERE ${vacateCountStatisticWhere.join(' AND ')} |
||||
|
`: ''}
|
||||
|
GROUP BY vacate.pep_user_id |
||||
|
) AS vacateCountStatistic |
||||
|
ON vacateCountStatistic.pepUserId = member.pep_user_id |
||||
|
`: ''}
|
||||
|
WHERE |
||||
|
member.del = '0' |
||||
|
${keywordTarget == 'post' && keyword ? ` |
||||
|
AND user.post IN ( |
||||
|
SELECT basicDataPost.id |
||||
|
FROM ${pepEmis}.basicdata_post AS basicDataPost |
||||
|
where basicDataPost.name LIKE '%${keyword}%' |
||||
|
) |
||||
|
` : ''}
|
||||
|
${keywordTarget == 'dep' && keyword ? ` |
||||
|
AND user.id IN ( |
||||
|
SELECT department_user.user |
||||
|
FROM ${pepEmis}.department_user AS department_user |
||||
|
INNER JOIN ${pepEmis}.department AS department |
||||
|
ON department.id = department_user.department |
||||
|
AND department.name LIKE '%${keyword}%' |
||||
|
) |
||||
|
` : ''}
|
||||
|
${state == 'dimission' ? `AND member.dimission_date IS NOT null` : ''} |
||||
|
${state == 'onJob' ? `AND member.dimission_date IS null` : ''} |
||||
|
${whereFromSelectOption.length && nowAttendanceTime ? `AND ${whereFromSelectOption.join('AND')}` : ''} |
||||
|
${hiredateStart ? ` |
||||
|
AND member.hiredate >= '${moment(hiredateStart).format('YYYY-MM-DD')}' |
||||
|
`: ''}
|
||||
|
${hiredateEnd ? `
|
||||
|
AND member.hiredate <= '${moment(hiredateEnd).format('YYYY-MM-DD')}' |
||||
|
` : ''}
|
||||
|
${marital ? ` |
||||
|
AND member.marital = '${marital}' |
||||
|
`: ''}
|
||||
|
${native ? ` |
||||
|
AND member.native_place = '${native}' |
||||
|
`: ''}
|
||||
|
${workPlace ? ` |
||||
|
AND member.work_place = '${workPlace}' |
||||
|
`: ''}
|
||||
|
` |
||||
|
|
||||
|
const userRes = await clickHouse.hr.query(` |
||||
|
SELECT |
||||
|
hrMember."member.pep_user_id" AS pepUserId, |
||||
|
hrMember.*, |
||||
|
user.name AS userName, |
||||
|
user.people_code AS userCode, |
||||
|
basicDataPost.name AS userPost, |
||||
|
role.name AS roleName, |
||||
|
role.id AS roleId, |
||||
|
department.name AS depName, |
||||
|
department.id AS depId, |
||||
|
user.job AS userJob, |
||||
|
user.active_status AS userActiveStatus, |
||||
|
user.organization AS userOrganization |
||||
|
FROM ( |
||||
|
SELECT |
||||
|
${orderBy == 'overtimeTakeRestSum' |
||||
|
|| orderBy == 'overtimePaySum' |
||||
|
|| orderBy == 'overtimeSum' ? ` |
||||
|
overtimeDayStatistic.duration AS overtimeDayStatisticDuration, |
||||
|
`: ''}
|
||||
|
|
||||
|
${overtimeCountStatistic ? ` |
||||
|
overtimeCountStatistic.count AS overtimeCount, |
||||
|
`: ''}
|
||||
|
|
||||
|
${orderBy == 'vacateSum' || vacateDurationStatistic ? ` |
||||
|
vacateDayStatistic.duration AS vacateDayStatisticDuration, |
||||
|
`: ''}
|
||||
|
|
||||
|
${vacateCountStatistic ? ` |
||||
|
vacateCountStatistic.count AS vacateCount, |
||||
|
`: ''}
|
||||
|
|
||||
|
${nowAttendanceTime ? ` |
||||
|
hrVacate.vacateStartTime AS vacateStartTime, |
||||
|
hrVacate.vacateEndTime AS vacateEndTime, |
||||
|
hrOvertime.overtimeStartTime AS overtimeStartTime, |
||||
|
hrOvertime.overtimeEndTime AS overtimeEndTime, |
||||
|
`: ''}
|
||||
|
|
||||
|
member.* |
||||
|
${innerSelectQuery} |
||||
|
${limit ? `LIMIT ${limit}` : ''} |
||||
|
${limit && page ? 'OFFSET ' + parseInt(limit) * parseInt(page) : ''} |
||||
|
) AS hrMember |
||||
|
|
||||
|
LEFT JOIN ${pepEmis}.user AS user |
||||
|
ON pepUserId = user.id |
||||
|
LEFT JOIN ${pepEmis}.user_role AS user_role |
||||
|
ON ${pepEmis}.user_role.user = user.id |
||||
|
LEFT JOIN ${pepEmis}.role AS role |
||||
|
ON ${pepEmis}.role.id = user_role.role |
||||
|
LEFT JOIN ${pepEmis}.basicdata_post AS basicDataPost |
||||
|
ON ${pepEmis}.basicdata_post.id = user.post |
||||
|
LEFT JOIN ${pepEmis}.department_user AS department_user |
||||
|
ON department_user.user = user.id |
||||
|
LEFT JOIN ${pepEmis}.department AS department |
||||
|
ON department.id = department_user.department |
||||
|
${whereOption.length ? `WHERE ${whereOption.join(' AND ')}` : ''} |
||||
|
ORDER BY ${orderBy == 'code' ? |
||||
|
'user.people_code' |
||||
|
: orderBy == 'hiredate' |
||||
|
? 'hrMember."member.hiredate"' |
||||
|
: orderBy == 'age' |
||||
|
? 'hrMember."member.birthday"' |
||||
|
: orderBy == 'overtimeTakeRestSum' |
||||
|
|| orderBy == 'overtimePaySum' |
||||
|
|| orderBy == 'overtimeSum' ? |
||||
|
'hrMember.overtimeDayStatisticDuration' |
||||
|
: orderBy == 'overtimeCount' ? |
||||
|
'hrMember.overtimeCount' |
||||
|
: orderBy == 'vacateSum' ? |
||||
|
'hrMember.vacateDayStatisticDuration' |
||||
|
: orderBy == 'vacateCount' ? |
||||
|
'hrMember.vacateCount' |
||||
|
: 'user.people_code'} |
||||
|
${orderDirection || 'ASC'} |
||||
|
`).toPromise()
|
||||
|
|
||||
|
const countRes = await clickHouse.hr.query(` |
||||
|
SELECT |
||||
|
count(member.pep_user_id) AS count |
||||
|
${innerSelectQuery} |
||||
|
`).toPromise()
|
||||
|
|
||||
|
return { |
||||
|
count: countRes[0].count, |
||||
|
rows: userRes |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
async function packageUserData (userRes, option = {}) { |
||||
|
|
||||
|
const { judgeHoliday, } = app.fs.utils |
||||
|
let workTime = false |
||||
|
let dayoffTime = false |
||||
|
if (option.state) { |
||||
|
const curDay = moment().format('YYYY-MM-DD') |
||||
|
const nowTime = moment() |
||||
|
const holidayJudge = await judgeHoliday(curDay) |
||||
|
if (holidayJudge) { |
||||
|
if ( |
||||
|
holidayJudge.workday |
||||
|
&& nowTime.isAfter(moment(curDay + ' 08:30')) |
||||
|
&& nowTime.isBefore(moment(curDay + ' 17:30')) |
||||
|
) { |
||||
|
workTime = true |
||||
|
} else if (holidayJudge.dayoff || holidayJudge.festivals) { |
||||
|
dayoffTime = true |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
let returnD = [] |
||||
|
let pepUserIds = [-1] |
||||
|
userRes.rows.forEach(u => { |
||||
|
let existUser = returnD.find(r => r.pepUserId == u.pepUserId) |
||||
|
if (existUser) { |
||||
|
if (u.depId && !existUser.departmrnt.some(d => d.id == u.depId)) { |
||||
|
existUser.departmrnt.push({ |
||||
|
id: u.depId, |
||||
|
name: u.depName |
||||
|
}) |
||||
|
} |
||||
|
if (u.roleId && !existUser.role.some(r => r.id == u.roleId)) { |
||||
|
existUser.role.push({ |
||||
|
id: u.roleId, |
||||
|
name: u.roleName |
||||
|
}) |
||||
|
} |
||||
|
} else { |
||||
|
let obj = {} |
||||
|
for (let k in u) { |
||||
|
let nextKey = k.replace('hrMember.', '') |
||||
|
.replace('member.', '') |
||||
|
if (nextKey.includes('_')) { |
||||
|
nextKey = nextKey.toLowerCase() |
||||
|
.replace( |
||||
|
/(_)[a-z]/g, |
||||
|
(L) => L.toUpperCase() |
||||
|
) |
||||
|
.replace(/_/g, '') |
||||
|
} |
||||
|
obj[nextKey] = u[k] == '1970-01-01 00:00:00.000000' || u[k] == '1970-01-01 08:00:00.000000' ? null : u[k] |
||||
|
} |
||||
|
pepUserIds.push(u.pepUserId) |
||||
|
console.log("查询到的用户信息:", obj); |
||||
|
returnD.push({ |
||||
|
...obj, |
||||
|
departmrnt: u.depId ? [{ |
||||
|
id: u.depId, |
||||
|
name: u.depName |
||||
|
}] : [], |
||||
|
role: u.roleId ? [{ |
||||
|
id: u.roleId, |
||||
|
name: u.roleName |
||||
|
}] : [], |
||||
|
state: option.state ? |
||||
|
obj['dimissionDate'] ? 'dimission' : |
||||
|
obj['vacateStartTime'] ? 'vacate' : |
||||
|
workTime ? 'inOffice' : |
||||
|
dayoffTime ? 'dayoff' : 'rest' |
||||
|
: undefined, |
||||
|
del: undefined, |
||||
|
pepuserid: undefined |
||||
|
}) |
||||
|
} |
||||
|
}) |
||||
|
return { packageUser: returnD, pepUserIds } |
||||
|
} |
||||
|
|
||||
|
return { |
||||
|
memberList, |
||||
|
packageUserData |
||||
|
} |
||||
|
} |
@ -0,0 +1,62 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
const moment = require('moment') |
||||
|
const Core = require('@alicloud/pop-core'); |
||||
|
const nodemailer = require('nodemailer') |
||||
|
|
||||
|
module.exports = function (app, opts) { |
||||
|
const pushBySms = async ({ phone = [], templateCode, templateParam } = {}) => { |
||||
|
try { |
||||
|
if (phone.length) { |
||||
|
const client = new Core({ |
||||
|
accessKeyId: opts.sms.accessKey, |
||||
|
accessKeySecret: opts.sms.accessSecret, |
||||
|
endpoint: 'http://dysmsapi.aliyuncs.com',//固定
|
||||
|
apiVersion: '2017-05-25'//固定
|
||||
|
}); |
||||
|
const SendSmsRes = await client.request('SendSms', { |
||||
|
"PhoneNumbers": phone.join(','),//接收短信的手机号码。
|
||||
|
"SignName": "飞尚尚视",//短信签名名称。必须是已添加、并通过审核的短信签名。
|
||||
|
"TemplateCode": templateCode,//短信模板ID。必须是已添加、并通过审核的短信签名;且发送国际/港澳台消息时,请使用国际/港澳台短信模版。
|
||||
|
"TemplateParam": JSON.stringify(templateParam)//短信模板变量对应的实际值,JSON格式。
|
||||
|
}, { |
||||
|
method: 'POST' |
||||
|
}); |
||||
|
return SendSmsRes |
||||
|
} |
||||
|
} catch (error) { |
||||
|
throw error |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
const pushByEmail = async ({ email = [], title, text = '', html = '', attachments = undefined } = {}) => { |
||||
|
try { |
||||
|
let transporter = nodemailer.createTransport({ |
||||
|
host: opts.email.host, |
||||
|
port: opts.email.port, |
||||
|
secure: true, |
||||
|
auth: { |
||||
|
user: opts.email.sender.address, |
||||
|
pass: opts.email.sender.password, |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// send mail with defined transport object
|
||||
|
await transporter.sendMail({ |
||||
|
from: `${opts.email.sender.name}<${opts.email.sender.address}>`, // sender address
|
||||
|
to: email.join(','), // list of receivers 逗号分隔字符串
|
||||
|
subject: title, // Subject line
|
||||
|
text: text, // plain text body
|
||||
|
html: html, // html body
|
||||
|
attachments: attachments |
||||
|
}); |
||||
|
} catch (error) { |
||||
|
throw error |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return { |
||||
|
pushByEmail, |
||||
|
pushBySms, |
||||
|
} |
||||
|
} |
@ -0,0 +1,82 @@ |
|||||
|
'use strict'; |
||||
|
const fs = require('fs'); |
||||
|
const xlsx = require('better-xlsx'); |
||||
|
const path = require('path') |
||||
|
const moment = require('moment') |
||||
|
|
||||
|
|
||||
|
module.exports = function (app, opts) { |
||||
|
|
||||
|
//递归创建目录 同步方法
|
||||
|
async function makeDir (dir) { |
||||
|
if (!fs.existsSync(dir)) { |
||||
|
makeDir(path.dirname(dir)) |
||||
|
fs.mkdirSync(dir, function (err) { |
||||
|
if (err) { |
||||
|
throw err |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
async function simpleExcelDown ({ data = [], header = [], fileName = moment().format('YYYY-MM-DD HH:mm:ss') } = {}) { |
||||
|
const fileDirPath = path.join(__dirname, `../../downloadFiles`) |
||||
|
makeDir(fileDirPath) |
||||
|
const file = new xlsx.File(); |
||||
|
const sheet_1 = file.addSheet('sheet_1'); |
||||
|
|
||||
|
// header
|
||||
|
const headerStyle = new xlsx.Style(); |
||||
|
headerStyle.align.h = 'center'; |
||||
|
headerStyle.align.v = 'center'; |
||||
|
headerStyle.border.right = 'thin'; |
||||
|
headerStyle.border.rightColor = '#000000'; |
||||
|
headerStyle.border.bottom = 'thin'; |
||||
|
headerStyle.border.bottomColor = '#000000'; |
||||
|
|
||||
|
const headerRow = sheet_1.addRow(); |
||||
|
const indexCell = headerRow.addCell(); |
||||
|
indexCell.value = '序号' |
||||
|
indexCell.style = headerStyle |
||||
|
for (let h of header) { |
||||
|
const cell = headerRow.addCell(); |
||||
|
cell.value = h.title; |
||||
|
cell.style = headerStyle |
||||
|
} |
||||
|
|
||||
|
// data
|
||||
|
const style = new xlsx.Style(); |
||||
|
style.align.h = 'left'; |
||||
|
style.align.v = 'center'; |
||||
|
style.border.right = 'thin'; |
||||
|
style.border.rightColor = '#000000'; |
||||
|
style.border.bottom = 'thin'; |
||||
|
style.border.bottomColor = '#000000'; |
||||
|
for (let i = 0; i < data.length; i++) { |
||||
|
const row = sheet_1.addRow(); |
||||
|
const indexCell = row.addCell(); |
||||
|
indexCell.value = i + 1 |
||||
|
indexCell.style = headerStyle |
||||
|
for (let h of header) { |
||||
|
const cell = row.addCell(); |
||||
|
cell.value = data[i][h.key] || h.defaultValue || '-'; |
||||
|
cell.style = style |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
const savePath = path.join(fileDirPath, fileName) |
||||
|
await new Promise(function (resolve, reject) { |
||||
|
file.saveAs() |
||||
|
.pipe(fs.createWriteStream(savePath)) |
||||
|
.on('finish', () => { |
||||
|
resolve() |
||||
|
}); |
||||
|
}) |
||||
|
return savePath |
||||
|
} |
||||
|
|
||||
|
return { |
||||
|
simpleExcelDown, |
||||
|
makeDir |
||||
|
} |
||||
|
} |
@ -0,0 +1,155 @@ |
|||||
|
'use strict'; |
||||
|
/*jslint node:true*/ |
||||
|
const path = require('path'); |
||||
|
const os = require('os'); |
||||
|
const moment = require('moment'); |
||||
|
const args = require('args'); |
||||
|
|
||||
|
const dev = process.env.NODE_ENV == 'development'; |
||||
|
|
||||
|
// 启动参数
|
||||
|
args.option(['p', 'port'], '启动端口'); |
||||
|
args.option(['g', 'pg'], 'postgre 服务 URL'); |
||||
|
|
||||
|
// 七牛云存储参数
|
||||
|
args.option('qnak', 'qiniuAccessKey'); |
||||
|
args.option('qnsk', 'qiniuSecretKey'); |
||||
|
args.option('qnbkt', 'qiniuBucket'); |
||||
|
args.option('qndmn', 'qiniuDomain'); |
||||
|
args.option('aliOssAccessKey', '阿里OSS AccessKey'); |
||||
|
args.option('aliOssSecretKey', '阿里OSS SecretKey'); |
||||
|
args.option('aliOssBucket', '阿里OSS Bucket'); |
||||
|
args.option('aliOssRegion', '阿里OSS Region'); |
||||
|
|
||||
|
const flags = args.parse(process.argv); |
||||
|
|
||||
|
const XUNJIAN_DB = process.env.XUNJIAN_DB || flags.pg; |
||||
|
|
||||
|
// 七牛云存储参数
|
||||
|
const QINIU_DOMAIN_QNDMN_RESOURCE = process.env.ANXINCLOUD_QINIU_DOMAIN_QNDMN_RESOURCE || flags.qndmn; |
||||
|
const QINIU_BUCKET_RESOURCE = process.env.ANXINCLOUD_QINIU_BUCKET_RESOURCE || flags.qnbkt; |
||||
|
const QINIU_AK = process.env.ANXINCLOUD_QINIU_ACCESSKEY || flags.qnak; |
||||
|
const QINIU_SK = process.env.ANXINCLOUD_QINIU_SECRETKEY || flags.qnsk; |
||||
|
|
||||
|
//阿里OSS
|
||||
|
const ALI_OSS_ACCESSKEY = process.env.ALI_OSS_ACCESSKEY || flags.aliOssAccessKey; |
||||
|
const ALI_OSS_SECRETKET = process.env.ALI_OSS_SECRETKET || flags.aliOssSecretKey; |
||||
|
const ALI_OSS_BUCKET = process.env.ALI_OSS_BUCKET || flags.aliOssBucket; |
||||
|
const ALI_OSS_REGION = process.env.ALI_OSS_REGION || flags.aliOssRegion; |
||||
|
|
||||
|
|
||||
|
if (!XUNJIAN_DB || !QINIU_DOMAIN_QNDMN_RESOURCE || !QINIU_BUCKET_RESOURCE || !QINIU_AK || !QINIU_SK) { |
||||
|
console.log('缺少启动参数,异常退出'); |
||||
|
args.showHelp(); |
||||
|
process.exit(-1); |
||||
|
} |
||||
|
|
||||
|
const product = { |
||||
|
port: flags.port || 8080, |
||||
|
staticDirs: ['static'], |
||||
|
mws: [ |
||||
|
{ |
||||
|
entry: require('@fs/attachment').entry, |
||||
|
opts: { |
||||
|
qiniu: { |
||||
|
domain: QINIU_DOMAIN_QNDMN_RESOURCE, |
||||
|
bucket: QINIU_BUCKET_RESOURCE, |
||||
|
accessKey: QINIU_AK, |
||||
|
secretKey: QINIU_SK |
||||
|
}, |
||||
|
maxSize: 104857600, // 100M
|
||||
|
} |
||||
|
}, { |
||||
|
entry: require('./app').entry, |
||||
|
opts: { |
||||
|
dev, |
||||
|
exclude: [ |
||||
|
// "*"
|
||||
|
], // 不做认证的路由,也可以使用 exclude: ["*"] 跳过所有路由
|
||||
|
qiniu: { |
||||
|
domain: QINIU_DOMAIN_QNDMN_RESOURCE, |
||||
|
bucket: QINIU_BUCKET_RESOURCE, |
||||
|
accessKey: QINIU_AK, |
||||
|
secretKey: QINIU_SK |
||||
|
}, |
||||
|
aliOss: { |
||||
|
accessKey: ALI_OSS_ACCESSKEY, |
||||
|
secretKey: ALI_OSS_SECRETKET, |
||||
|
bucket: ALI_OSS_BUCKET, |
||||
|
region: ALI_OSS_REGION |
||||
|
}, |
||||
|
sms: { |
||||
|
///阿里云-安心云
|
||||
|
accessKey: 'LTAI5tAFdjz7j38aNF2C9Qe8', |
||||
|
accessSecret: '1trYkmiqfBtvZL6BxkNH2uQcQQPs0S' |
||||
|
}, |
||||
|
email: { |
||||
|
enabled: true, |
||||
|
host: 'smtp.exmail.qq.com', |
||||
|
port: 465, |
||||
|
sender: { |
||||
|
name: '中鼎服务', |
||||
|
address: 'fsiot@free-sun.com.cn', |
||||
|
password: 'Fs2689' |
||||
|
} |
||||
|
}, |
||||
|
} |
||||
|
} |
||||
|
], |
||||
|
dc: { |
||||
|
url: XUNJIAN_DB, |
||||
|
opts: { |
||||
|
pool: { |
||||
|
max: 80, |
||||
|
min: 10, |
||||
|
idle: 10000 |
||||
|
}, |
||||
|
define: { |
||||
|
freezeTableName: true, // 固定表名
|
||||
|
timestamps: false // 不含列 "createAt"/"updateAt"/"DeleteAt"
|
||||
|
}, |
||||
|
timezone: '+08:00', |
||||
|
logging: false |
||||
|
}, |
||||
|
models: [require('./app').models] |
||||
|
}, |
||||
|
logger: { |
||||
|
level: 'info', |
||||
|
json: false, |
||||
|
filename: path.join(__dirname, 'log', 'runtime.log'), |
||||
|
colorize: false, |
||||
|
maxsize: 1024 * 1024 * 5, |
||||
|
rotationFormat: false, |
||||
|
zippedArchive: true, |
||||
|
maxFiles: 10, |
||||
|
prettyPrint: true, |
||||
|
label: '', |
||||
|
timestamp: () => moment().format('YYYY-MM-DD HH:mm:ss.SSS'), |
||||
|
eol: os.EOL, |
||||
|
tailable: true, |
||||
|
depth: null, |
||||
|
showLevel: true, |
||||
|
maxRetries: 1 |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
const development = { |
||||
|
port: product.port, |
||||
|
staticDirs: product.staticDirs, |
||||
|
mws: product.mws, |
||||
|
dc: product.dc, |
||||
|
logger: product.logger |
||||
|
}; |
||||
|
|
||||
|
if (dev) { |
||||
|
// mws
|
||||
|
for (let mw of development.mws) { |
||||
|
// if (mw.opts.exclude) mw.opts.exclude = ['*']; // 使用 ['*'] 跳过所有路由
|
||||
|
} |
||||
|
// logger
|
||||
|
development.logger.filename = path.join(__dirname, 'log', 'development.log'); |
||||
|
development.logger.level = 'debug'; |
||||
|
development.dc.opts.logging = console.log; |
||||
|
} |
||||
|
|
||||
|
module.exports = dev ? development : product; |
@ -0,0 +1,48 @@ |
|||||
|
{ |
||||
|
"name": "smart-emergency", |
||||
|
"version": "1.0.0", |
||||
|
"description": "fs smart emergency api", |
||||
|
"main": "server.js", |
||||
|
"scripts": { |
||||
|
"test": "set DEBUG=true&&\"node_modules/.bin/mocha\" --harmony --reporter spec app/test/*.test.js", |
||||
|
"start": "set NODE_ENV=development&&node server -p 4000 -g postgres://postgres:123@10.8.30.32:5432/video_access -f http://localhost:4000", |
||||
|
"start:linux": "export NODE_ENV=development&&node server -p 4000 -g postgres://FashionAdmin:123456@10.8.30.39:5432/pm1", |
||||
|
"automate": "sequelize-automate -c sequelize-automate.config.js" |
||||
|
}, |
||||
|
"author": "", |
||||
|
"license": "MIT", |
||||
|
"repository": {}, |
||||
|
"dependencies": { |
||||
|
"@alicloud/pop-core": "^1.7.12", |
||||
|
"@fs/attachment": "^1.0.0", |
||||
|
"ali-oss": "^6.17.1", |
||||
|
"args": "^3.0.7", |
||||
|
"better-xlsx": "^0.7.6", |
||||
|
"clickhouse": "^2.6.0", |
||||
|
"crypto-js": "^4.0.0", |
||||
|
"file-saver": "^2.0.2", |
||||
|
"fs-web-server-scaffold": "^2.0.2", |
||||
|
"ioredis": "^5.0.4", |
||||
|
"kafka-node": "^2.2.3", |
||||
|
"koa-convert": "^1.2.0", |
||||
|
"koa-proxy": "^0.9.0", |
||||
|
"moment": "^2.24.0", |
||||
|
"mqtt": "^4.3.7", |
||||
|
"node-schedule": "^2.1.0", |
||||
|
"nodemailer": "^6.7.7", |
||||
|
"path": "^0.12.7", |
||||
|
"path-to-regexp": "^3.0.0", |
||||
|
"pg": "^7.9.0", |
||||
|
"qrcode": "^1.5.1", |
||||
|
"qs": "^6.11.0", |
||||
|
"redis": "^3.1.2", |
||||
|
"request": "^2.88.2", |
||||
|
"rimraf": "^2.6.3", |
||||
|
"shortid": "^2.2.16", |
||||
|
"superagent": "^3.5.2", |
||||
|
"uuid": "^3.3.2" |
||||
|
}, |
||||
|
"devDependencies": { |
||||
|
"mocha": "^6.0.2" |
||||
|
} |
||||
|
} |
@ -0,0 +1,35 @@ |
|||||
|
module.exports = { |
||||
|
// 数据库配置 与 sequelize 相同
|
||||
|
dbOptions: { |
||||
|
database: 'ZhongDing', |
||||
|
username: 'FashionAdmin', |
||||
|
password: '123456', |
||||
|
dialect: 'postgres', |
||||
|
host: '10.8.30.39', |
||||
|
port: 5432, |
||||
|
define: { |
||||
|
underscored: false, |
||||
|
freezeTableName: false, |
||||
|
charset: 'utf8mb4', |
||||
|
timezone: '+00: 00', |
||||
|
dialectOptions: { |
||||
|
collate: 'utf8_general_ci', |
||||
|
}, |
||||
|
timestamps: false, |
||||
|
}, |
||||
|
}, |
||||
|
options: { |
||||
|
type: 'freesun', // 指定 models 代码风格
|
||||
|
camelCase: true, // Models 文件中代码是否使用驼峰命名
|
||||
|
modalNameSuffix: false, // 模型名称是否带 ‘Model’ 后缀
|
||||
|
fileNameCamelCase: false, // Model 文件名是否使用驼峰法命名,默认文件名会使用表名,如 `user_post.js`;如果为 true,则文件名为 `userPost.js`
|
||||
|
dir: './app/lib/models', // 指定输出 models 文件的目录
|
||||
|
typesDir: 'models', // 指定输出 TypeScript 类型定义的文件目录,只有 TypeScript / Midway 等会有类型定义
|
||||
|
emptyDir: false, // !!! 谨慎操作 生成 models 之前是否清空 `dir` 以及 `typesDir`
|
||||
|
tables: ['hide_danger_report'], // 指定生成哪些表的 models,如 ['user', 'user_post'];如果为 null,则忽略改属性
|
||||
|
skipTables: [], // 指定跳过哪些表的 models,如 ['user'];如果为 null,则忽略改属性
|
||||
|
tsNoCheck: false, // 是否添加 `@ts-nocheck` 注释到 models 文件中
|
||||
|
ignorePrefix: ['t_',], // 生成的模型名称忽略的前缀,因为 项目中有以下表名是以 t_ 开头的,在实际模型中不需要, 可以添加多个 [ 't_data_', 't_',] ,长度较长的 前缀放前面
|
||||
|
attrLength: false, // 在生成模型的字段中 是否生成 如 var(128)这种格式,公司一般使用 String ,则配置为 false
|
||||
|
}, |
||||
|
} |
@ -0,0 +1,12 @@ |
|||||
|
/** |
||||
|
* Created by rain on 2016/1/25. |
||||
|
*/ |
||||
|
|
||||
|
'use strict'; |
||||
|
/*jslint node:true*/ |
||||
|
//from koa
|
||||
|
|
||||
|
const scaffold = require('fs-web-server-scaffold'); |
||||
|
const config = require('./config'); |
||||
|
|
||||
|
module.exports = scaffold(config); |
@ -0,0 +1,18 @@ |
|||||
|
pipeline { |
||||
|
agent { |
||||
|
node{ |
||||
|
label 'jnlp-slave' |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
stages { |
||||
|
stage('巡检 api ......') { |
||||
|
steps { |
||||
|
buildName "#${BUILD_NUMBER} ~/smartcity/${JOB_NAME}:${IMAGE_VERSION}" |
||||
|
buildDescription "harbor.anxinyun.cn/smartcity/${JOB_NAME}:${IMAGE_VERSION}" |
||||
|
sh 'nerdctl build -t harbor.anxinyun.cn/smartcity/${JOB_NAME}:${IMAGE_VERSION} ./api' |
||||
|
sh 'nerdctl push harbor.anxinyun.cn/smartcity/${JOB_NAME}:${IMAGE_VERSION}' |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,18 @@ |
|||||
|
pipeline { |
||||
|
agent { |
||||
|
node{ |
||||
|
label 'jnlp-slave' |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
stages { |
||||
|
stage('巡检 web ......') { |
||||
|
steps { |
||||
|
buildName "#${BUILD_NUMBER} ~/smartcity/${JOB_NAME}:${IMAGE_VERSION}" |
||||
|
buildDescription "harbor.anxinyun.cn/smartcity/${JOB_NAME}:${IMAGE_VERSION}" |
||||
|
sh 'nerdctl build -t harbor.anxinyun.cn/smartcity/${JOB_NAME}:${IMAGE_VERSION} ./web' |
||||
|
sh 'nerdctl push harbor.anxinyun.cn/smartcity/${JOB_NAME}:${IMAGE_VERSION}' |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,19 @@ |
|||||
|
{ |
||||
|
"presets": [ |
||||
|
"@babel/preset-react", |
||||
|
"@babel/preset-env" |
||||
|
|
||||
|
], |
||||
|
"plugins": [ |
||||
|
"@babel/plugin-proposal-class-properties", |
||||
|
"@babel/plugin-proposal-object-rest-spread", |
||||
|
["import", { |
||||
|
"libraryName": "antd", |
||||
|
"libraryDirectory": "es" |
||||
|
|
||||
|
}] |
||||
|
], |
||||
|
"env": { |
||||
|
"development": {} |
||||
|
} |
||||
|
} |
@ -0,0 +1,23 @@ |
|||||
|
{ |
||||
|
"version": "0.2.0", |
||||
|
"configurations": [ |
||||
|
{ |
||||
|
"name": "Server", |
||||
|
"type": "node", |
||||
|
"request": "launch", |
||||
|
"program": "${workspaceRoot}/server.js", |
||||
|
"args": [ |
||||
|
"-u http://127.0.0.1:4000", |
||||
|
//阿里OSS |
||||
|
"--aliOssAccessKey LTAI5tNDfn7UhStYQcn3JBtw", |
||||
|
"--aliOssSecretKey rnoXtDWQA1djJ5Xqcdn1OSEol0lVyv", |
||||
|
"--aliOssBucket test-c371", |
||||
|
"--aliOssRegion oss-cn-hangzhou", |
||||
|
], |
||||
|
"outputCapture": "std", |
||||
|
"env": { |
||||
|
"NODE_ENV": "development" |
||||
|
} |
||||
|
} |
||||
|
] |
||||
|
} |
@ -0,0 +1,4 @@ |
|||||
|
// 将设置放入此文件中以覆盖默认值和用户设置。 |
||||
|
{ |
||||
|
"editor.fontSize": 16, |
||||
|
} |
@ -0,0 +1,56 @@ |
|||||
|
#FROM repository.anxinyun.cn/base-images/nodejs12:20.10.12.2 |
||||
|
FROM repository.anxinyun.cn/base-images/nodejs12:20.10.12.2 |
||||
|
COPY . /var/app |
||||
|
WORKDIR /var/app |
||||
|
EXPOSE 8080 |
||||
|
|
||||
|
RUN apk update && apk add --no-cache \ |
||||
|
sudo \ |
||||
|
curl \ |
||||
|
build-base \ |
||||
|
g++ \ |
||||
|
libpng \ |
||||
|
libpng-dev \ |
||||
|
jpeg-dev \ |
||||
|
pango-dev \ |
||||
|
cairo-dev \ |
||||
|
giflib-dev \ |
||||
|
python \ |
||||
|
; |
||||
|
RUN npm config set registry=http://10.8.30.22:7000 |
||||
|
RUN npm cache clean -f |
||||
|
#RUN npm install -g node-gyp |
||||
|
RUN rm -rf package-lock.json |
||||
|
RUN npm install --registry http://10.8.30.22:7000 |
||||
|
RUN npm run build |
||||
|
RUN rm -rf client/src |
||||
|
RUN rm -rf node_modules |
||||
|
RUN npm install --production --registry http://10.8.30.22:7000 |
||||
|
#RUN npm cache clean -f && npm install --production --force --registry http://10.8.30.22:7000 |
||||
|
CMD ["-u", "http://localhost:8088"] |
||||
|
ENTRYPOINT [ "node", "server.js" ] |
||||
|
|
||||
|
# FROM registry.cn-hangzhou.aliyuncs.com/fs-devops/node:12-dev as builder |
||||
|
|
||||
|
# COPY . /var/app |
||||
|
|
||||
|
# WORKDIR /var/app |
||||
|
|
||||
|
# EXPOSE 8080 |
||||
|
|
||||
|
# RUN npm config set registry=http://10.8.30.22:7000 |
||||
|
# RUN echo "{\"time\":\"$BUILD_TIMESTAMP\",\"build\": \"$BUILD_NUMBER\",\"revision\": \"$SVN_REVISION_1\",\"URL\":\"$SVN_URL_1\"}" > version.json |
||||
|
# RUN npm cache clean -f |
||||
|
# RUN rm -rf package-lock.json |
||||
|
# RUN npm install --registry http://10.8.30.22:7000 |
||||
|
# RUN npm run build |
||||
|
# RUN rm -rf client/src |
||||
|
# RUN rm -rf node_modules |
||||
|
# RUN npm install --production --force --registry http://10.8.30.22:7000 |
||||
|
# FROM registry.cn-hangzhou.aliyuncs.com/fs-devops/node:12 |
||||
|
|
||||
|
# COPY --from=builder --chown=node /var/app /home/node/app |
||||
|
|
||||
|
# WORKDIR /home/node/app |
||||
|
|
||||
|
# CMD ["node", "server.js"] |
@ -0,0 +1,370 @@ |
|||||
|
*{margin: 0;padding: 0;list-style: none;} |
||||
|
/* |
||||
|
KISSY CSS Reset |
||||
|
理念:1. reset 的目的不是清除浏览器的默认样式,这仅是部分工作。清除和重置是紧密不可分的。 |
||||
|
2. reset 的目的不是让默认样式在所有浏览器下一致,而是减少默认样式有可能带来的问题。 |
||||
|
3. reset 期望提供一套普适通用的基础样式。但没有银弹,推荐根据具体需求,裁剪和修改后再使用。 |
||||
|
特色:1. 适应中文;2. 基于最新主流浏览器。 |
||||
|
维护:玉伯<lifesinger@gmail.com>, 正淳<ragecarrier@gmail.com> |
||||
|
*/ |
||||
|
|
||||
|
/** 清除内外边距 **/ |
||||
|
body, h1, h2, h3, h4, h5, h6, hr, p, blockquote, /* structural elements 结构元素 */ |
||||
|
dl, dt, dd, ul, ol, li, /* list elements 列表元素 */ |
||||
|
pre, /* text formatting elements 文本格式元素 */ |
||||
|
form, fieldset, legend, button, input, textarea, /* form elements 表单元素 */ |
||||
|
th, td /* table elements 表格元素 */ { |
||||
|
margin: 0; |
||||
|
padding: 0; |
||||
|
} |
||||
|
|
||||
|
/** 设置默认字体 **/ |
||||
|
body, |
||||
|
button, input, select, textarea /* for ie */ { |
||||
|
font: 12px/1.5 tahoma, arial, \5b8b\4f53, sans-serif; |
||||
|
} |
||||
|
h1, h2, h3, h4, h5, h6 { font-size: 100%; } |
||||
|
address, cite, dfn, em, var { font-style: normal; } /* 将斜体扶正 */ |
||||
|
code, kbd, pre, samp { font-family: courier new, courier, monospace; } /* 统一等宽字体 */ |
||||
|
small { font-size: 12px; } /* 小于 12px 的中文很难阅读,让 small 正常化 */ |
||||
|
|
||||
|
/** 重置列表元素 **/ |
||||
|
ul, ol { list-style: none; } |
||||
|
|
||||
|
/** 重置文本格式元素 **/ |
||||
|
a { text-decoration: none; } |
||||
|
a:hover { text-decoration: underline; } |
||||
|
|
||||
|
|
||||
|
/** 重置表单元素 **/ |
||||
|
legend { color: #000; } /* for ie6 */ |
||||
|
fieldset, img { border: 0; } /* img 搭车:让链接里的 img 无边框 */ |
||||
|
button, input, select, textarea { font-size: 100%; } /* 使得表单元素在 ie 下能继承字体大小 */ |
||||
|
/* 注:optgroup 无法扶正 */ |
||||
|
|
||||
|
/** 重置表格元素 **/ |
||||
|
table { border-collapse: collapse; border-spacing: 0; } |
||||
|
|
||||
|
/* 清除浮动 */ |
||||
|
.ks-clear:after, .clear:after { |
||||
|
content: '\20'; |
||||
|
display: block; |
||||
|
height: 0; |
||||
|
clear: both; |
||||
|
} |
||||
|
.ks-clear, .clear { |
||||
|
*zoom: 1; |
||||
|
} |
||||
|
|
||||
|
.main { |
||||
|
padding: 30px 100px; |
||||
|
width: 960px; |
||||
|
margin: 0 auto; |
||||
|
} |
||||
|
.main h1{font-size:36px; color:#333; text-align:left;margin-bottom:30px; border-bottom: 1px solid #eee;} |
||||
|
|
||||
|
.helps{margin-top:40px;} |
||||
|
.helps pre{ |
||||
|
padding:20px; |
||||
|
margin:10px 0; |
||||
|
border:solid 1px #e7e1cd; |
||||
|
background-color: #fffdef; |
||||
|
overflow: auto; |
||||
|
} |
||||
|
|
||||
|
.icon_lists{ |
||||
|
width: 100% !important; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
.icon_lists li{ |
||||
|
float:left; |
||||
|
width: 100px; |
||||
|
height:180px; |
||||
|
text-align: center; |
||||
|
list-style: none !important; |
||||
|
} |
||||
|
.icon_lists .icon{ |
||||
|
font-size: 42px; |
||||
|
line-height: 100px; |
||||
|
margin: 10px 0; |
||||
|
color:#333; |
||||
|
-webkit-transition: font-size 0.25s ease-out 0s; |
||||
|
-moz-transition: font-size 0.25s ease-out 0s; |
||||
|
transition: font-size 0.25s ease-out 0s; |
||||
|
|
||||
|
} |
||||
|
.icon_lists .icon:hover{ |
||||
|
font-size: 100px; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
.markdown { |
||||
|
color: #666; |
||||
|
font-size: 14px; |
||||
|
line-height: 1.8; |
||||
|
} |
||||
|
|
||||
|
.highlight { |
||||
|
line-height: 1.5; |
||||
|
} |
||||
|
|
||||
|
.markdown img { |
||||
|
vertical-align: middle; |
||||
|
max-width: 100%; |
||||
|
} |
||||
|
|
||||
|
.markdown h1 { |
||||
|
color: #404040; |
||||
|
font-weight: 500; |
||||
|
line-height: 40px; |
||||
|
margin-bottom: 24px; |
||||
|
} |
||||
|
|
||||
|
.markdown h2, |
||||
|
.markdown h3, |
||||
|
.markdown h4, |
||||
|
.markdown h5, |
||||
|
.markdown h6 { |
||||
|
color: #404040; |
||||
|
margin: 1.6em 0 0.6em 0; |
||||
|
font-weight: 500; |
||||
|
clear: both; |
||||
|
} |
||||
|
|
||||
|
.markdown h1 { |
||||
|
font-size: 28px; |
||||
|
} |
||||
|
|
||||
|
.markdown h2 { |
||||
|
font-size: 22px; |
||||
|
} |
||||
|
|
||||
|
.markdown h3 { |
||||
|
font-size: 16px; |
||||
|
} |
||||
|
|
||||
|
.markdown h4 { |
||||
|
font-size: 14px; |
||||
|
} |
||||
|
|
||||
|
.markdown h5 { |
||||
|
font-size: 12px; |
||||
|
} |
||||
|
|
||||
|
.markdown h6 { |
||||
|
font-size: 12px; |
||||
|
} |
||||
|
|
||||
|
.markdown hr { |
||||
|
height: 1px; |
||||
|
border: 0; |
||||
|
background: #e9e9e9; |
||||
|
margin: 16px 0; |
||||
|
clear: both; |
||||
|
} |
||||
|
|
||||
|
.markdown p, |
||||
|
.markdown pre { |
||||
|
margin: 1em 0; |
||||
|
} |
||||
|
|
||||
|
.markdown > p, |
||||
|
.markdown > blockquote, |
||||
|
.markdown > .highlight, |
||||
|
.markdown > ol, |
||||
|
.markdown > ul { |
||||
|
width: 80%; |
||||
|
} |
||||
|
|
||||
|
.markdown ul > li { |
||||
|
list-style: circle; |
||||
|
} |
||||
|
|
||||
|
.markdown > ul li, |
||||
|
.markdown blockquote ul > li { |
||||
|
margin-left: 20px; |
||||
|
padding-left: 4px; |
||||
|
} |
||||
|
|
||||
|
.markdown > ul li p, |
||||
|
.markdown > ol li p { |
||||
|
margin: 0.6em 0; |
||||
|
} |
||||
|
|
||||
|
.markdown ol > li { |
||||
|
list-style: decimal; |
||||
|
} |
||||
|
|
||||
|
.markdown > ol li, |
||||
|
.markdown blockquote ol > li { |
||||
|
margin-left: 20px; |
||||
|
padding-left: 4px; |
||||
|
} |
||||
|
|
||||
|
.markdown code { |
||||
|
margin: 0 3px; |
||||
|
padding: 0 5px; |
||||
|
background: #eee; |
||||
|
border-radius: 3px; |
||||
|
} |
||||
|
|
||||
|
.markdown pre { |
||||
|
border-radius: 6px; |
||||
|
background: #f7f7f7; |
||||
|
padding: 20px; |
||||
|
} |
||||
|
|
||||
|
.markdown pre code { |
||||
|
border: none; |
||||
|
background: #f7f7f7; |
||||
|
margin: 0; |
||||
|
} |
||||
|
|
||||
|
.markdown strong, |
||||
|
.markdown b { |
||||
|
font-weight: 600; |
||||
|
} |
||||
|
|
||||
|
.markdown > table { |
||||
|
border-collapse: collapse; |
||||
|
border-spacing: 0px; |
||||
|
empty-cells: show; |
||||
|
border: 1px solid #e9e9e9; |
||||
|
width: 95%; |
||||
|
margin-bottom: 24px; |
||||
|
} |
||||
|
|
||||
|
.markdown > table th { |
||||
|
white-space: nowrap; |
||||
|
color: #333; |
||||
|
font-weight: 600; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
.markdown > table th, |
||||
|
.markdown > table td { |
||||
|
border: 1px solid #e9e9e9; |
||||
|
padding: 8px 16px; |
||||
|
text-align: left; |
||||
|
} |
||||
|
|
||||
|
.markdown > table th { |
||||
|
background: #F7F7F7; |
||||
|
} |
||||
|
|
||||
|
.markdown blockquote { |
||||
|
font-size: 90%; |
||||
|
color: #999; |
||||
|
border-left: 4px solid #e9e9e9; |
||||
|
padding-left: 0.8em; |
||||
|
margin: 1em 0; |
||||
|
font-style: italic; |
||||
|
} |
||||
|
|
||||
|
.markdown blockquote p { |
||||
|
margin: 0; |
||||
|
} |
||||
|
|
||||
|
.markdown .anchor { |
||||
|
opacity: 0; |
||||
|
transition: opacity 0.3s ease; |
||||
|
margin-left: 8px; |
||||
|
} |
||||
|
|
||||
|
.markdown .waiting { |
||||
|
color: #ccc; |
||||
|
} |
||||
|
|
||||
|
.markdown h1:hover .anchor, |
||||
|
.markdown h2:hover .anchor, |
||||
|
.markdown h3:hover .anchor, |
||||
|
.markdown h4:hover .anchor, |
||||
|
.markdown h5:hover .anchor, |
||||
|
.markdown h6:hover .anchor { |
||||
|
opacity: 1; |
||||
|
display: inline-block; |
||||
|
} |
||||
|
|
||||
|
.markdown > br, |
||||
|
.markdown > p > br { |
||||
|
clear: both; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
.hljs { |
||||
|
display: block; |
||||
|
background: white; |
||||
|
padding: 0.5em; |
||||
|
color: #333333; |
||||
|
overflow-x: auto; |
||||
|
} |
||||
|
|
||||
|
.hljs-comment, |
||||
|
.hljs-meta { |
||||
|
color: #969896; |
||||
|
} |
||||
|
|
||||
|
.hljs-string, |
||||
|
.hljs-variable, |
||||
|
.hljs-template-variable, |
||||
|
.hljs-strong, |
||||
|
.hljs-emphasis, |
||||
|
.hljs-quote { |
||||
|
color: #df5000; |
||||
|
} |
||||
|
|
||||
|
.hljs-keyword, |
||||
|
.hljs-selector-tag, |
||||
|
.hljs-type { |
||||
|
color: #a71d5d; |
||||
|
} |
||||
|
|
||||
|
.hljs-literal, |
||||
|
.hljs-symbol, |
||||
|
.hljs-bullet, |
||||
|
.hljs-attribute { |
||||
|
color: #0086b3; |
||||
|
} |
||||
|
|
||||
|
.hljs-section, |
||||
|
.hljs-name { |
||||
|
color: #63a35c; |
||||
|
} |
||||
|
|
||||
|
.hljs-tag { |
||||
|
color: #333333; |
||||
|
} |
||||
|
|
||||
|
.hljs-title, |
||||
|
.hljs-attr, |
||||
|
.hljs-selector-id, |
||||
|
.hljs-selector-class, |
||||
|
.hljs-selector-attr, |
||||
|
.hljs-selector-pseudo { |
||||
|
color: #795da3; |
||||
|
} |
||||
|
|
||||
|
.hljs-addition { |
||||
|
color: #55a532; |
||||
|
background-color: #eaffea; |
||||
|
} |
||||
|
|
||||
|
.hljs-deletion { |
||||
|
color: #bd2c00; |
||||
|
background-color: #ffecec; |
||||
|
} |
||||
|
|
||||
|
.hljs-link { |
||||
|
text-decoration: underline; |
||||
|
} |
||||
|
|
||||
|
pre{ |
||||
|
background: #fff; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
@ -0,0 +1,514 @@ |
|||||
|
|
||||
|
<!DOCTYPE html> |
||||
|
<html> |
||||
|
<head> |
||||
|
<meta charset="utf-8"/> |
||||
|
<title>IconFont</title> |
||||
|
<link rel="stylesheet" href="demo.css"> |
||||
|
<link rel="stylesheet" href="iconfont.css"> |
||||
|
</head> |
||||
|
<body> |
||||
|
<div class="main markdown"> |
||||
|
<h1>IconFont 图标</h1> |
||||
|
<ul class="icon_lists clear"> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-liuliang"></i> |
||||
|
<div class="name">流量</div> |
||||
|
<div class="fontclass">.icon-liuliang</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-iconfontditie"></i> |
||||
|
<div class="name">轻轨</div> |
||||
|
<div class="fontclass">.icon-iconfontditie</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-fengsu3"></i> |
||||
|
<div class="name">风速3</div> |
||||
|
<div class="fontclass">.icon-fengsu3</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-calendar"></i> |
||||
|
<div class="name">calendar</div> |
||||
|
<div class="fontclass">.icon-calendar</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-box"></i> |
||||
|
<div class="name">box</div> |
||||
|
<div class="fontclass">.icon-box</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-shenheshibai"></i> |
||||
|
<div class="name">审核失败</div> |
||||
|
<div class="fontclass">.icon-shenheshibai</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-slope"></i> |
||||
|
<div class="name">边坡</div> |
||||
|
<div class="fontclass">.icon-slope</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-icon2"></i> |
||||
|
<div class="name">公路</div> |
||||
|
<div class="fontclass">.icon-icon2</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-gnsscaidian"></i> |
||||
|
<div class="name">GNSS采点</div> |
||||
|
<div class="fontclass">.icon-gnsscaidian</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-chuanganqishebei"></i> |
||||
|
<div class="name">传感器设备</div> |
||||
|
<div class="fontclass">.icon-chuanganqishebei</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-dianliuchuanganqi"></i> |
||||
|
<div class="name">电流传感器</div> |
||||
|
<div class="fontclass">.icon-dianliuchuanganqi</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-dianyachuanganqi"></i> |
||||
|
<div class="name">电压传感器</div> |
||||
|
<div class="fontclass">.icon-dianyachuanganqi</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-wenduchuanganqi"></i> |
||||
|
<div class="name">温度传感器</div> |
||||
|
<div class="fontclass">.icon-wenduchuanganqi</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-xinjian"></i> |
||||
|
<div class="name">新建</div> |
||||
|
<div class="fontclass">.icon-xinjian</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-handong"></i> |
||||
|
<div class="name">涵洞</div> |
||||
|
<div class="fontclass">.icon-handong</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-guanwanggongcheng"></i> |
||||
|
<div class="name">管网工程</div> |
||||
|
<div class="fontclass">.icon-guanwanggongcheng</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-shenhe"></i> |
||||
|
<div class="name">审核</div> |
||||
|
<div class="fontclass">.icon-shenhe</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-zhihuishequ"></i> |
||||
|
<div class="name">智慧城市</div> |
||||
|
<div class="fontclass">.icon-zhihuishequ</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-bianpoweiyi"></i> |
||||
|
<div class="name">边坡位移</div> |
||||
|
<div class="fontclass">.icon-bianpoweiyi</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-jianzhu"></i> |
||||
|
<div class="name">建筑</div> |
||||
|
<div class="fontclass">.icon-jianzhu</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-chuguan"></i> |
||||
|
<div class="name">储罐</div> |
||||
|
<div class="fontclass">.icon-chuguan</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-suidao"></i> |
||||
|
<div class="name">隧道</div> |
||||
|
<div class="fontclass">.icon-suidao</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-data"></i> |
||||
|
<div class="name">data</div> |
||||
|
<div class="fontclass">.icon-data</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-kuangshankaicai"></i> |
||||
|
<div class="name">矿山开采</div> |
||||
|
<div class="fontclass">.icon-kuangshankaicai</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-wangluo"></i> |
||||
|
<div class="name">网络</div> |
||||
|
<div class="fontclass">.icon-wangluo</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-jiankong"></i> |
||||
|
<div class="name">监控</div> |
||||
|
<div class="fontclass">.icon-jiankong</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-dashuju"></i> |
||||
|
<div class="name">大数据</div> |
||||
|
<div class="fontclass">.icon-dashuju</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-shuju"></i> |
||||
|
<div class="name">数据库</div> |
||||
|
<div class="fontclass">.icon-shuju</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-shenhechenggong"></i> |
||||
|
<div class="name">审核成功</div> |
||||
|
<div class="fontclass">.icon-shenhechenggong</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-jiankong1"></i> |
||||
|
<div class="name">监控</div> |
||||
|
<div class="fontclass">.icon-jiankong1</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-wangluoxitong"></i> |
||||
|
<div class="name">网络系统</div> |
||||
|
<div class="fontclass">.icon-wangluoxitong</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-dingwei"></i> |
||||
|
<div class="name">定位</div> |
||||
|
<div class="fontclass">.icon-dingwei</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-xitongyunzhuanqingkuang"></i> |
||||
|
<div class="name">系统运转情况</div> |
||||
|
<div class="fontclass">.icon-xitongyunzhuanqingkuang</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-chakan"></i> |
||||
|
<div class="name">查看</div> |
||||
|
<div class="fontclass">.icon-chakan</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-lianjie"></i> |
||||
|
<div class="name">链接</div> |
||||
|
<div class="fontclass">.icon-lianjie</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-shujudaochu-01"></i> |
||||
|
<div class="name">数据导出-01</div> |
||||
|
<div class="fontclass">.icon-shujudaochu-01</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-xitongzhuangtai"></i> |
||||
|
<div class="name">系统状态</div> |
||||
|
<div class="fontclass">.icon-xitongzhuangtai</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-xiaofeimingxidan"></i> |
||||
|
<div class="name">消费明细单</div> |
||||
|
<div class="fontclass">.icon-xiaofeimingxidan</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-SQLshenhe"></i> |
||||
|
<div class="name">SQL审核</div> |
||||
|
<div class="fontclass">.icon-SQLshenhe</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-aislogo"></i> |
||||
|
<div class="name">aislogo</div> |
||||
|
<div class="fontclass">.icon-aislogo</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-qiao"></i> |
||||
|
<div class="name">桥</div> |
||||
|
<div class="fontclass">.icon-qiao</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-tashiqizhongji"></i> |
||||
|
<div class="name">塔式起重机</div> |
||||
|
<div class="fontclass">.icon-tashiqizhongji</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-dwggeshi"></i> |
||||
|
<div class="name">dwg格式</div> |
||||
|
<div class="fontclass">.icon-dwggeshi</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-luyouqi"></i> |
||||
|
<div class="name">路由器</div> |
||||
|
<div class="fontclass">.icon-luyouqi</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-anzhuangshigong-xianxing"></i> |
||||
|
<div class="name">244安装、施工-线性</div> |
||||
|
<div class="fontclass">.icon-anzhuangshigong-xianxing</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-shaixuanguolv"></i> |
||||
|
<div class="name">245筛选过滤</div> |
||||
|
<div class="fontclass">.icon-shaixuanguolv</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-anzhuangshigong"></i> |
||||
|
<div class="name">244安装、施工</div> |
||||
|
<div class="fontclass">.icon-anzhuangshigong</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-tiaoxingtu-xianxing"></i> |
||||
|
<div class="name">408条形图-线性</div> |
||||
|
<div class="fontclass">.icon-tiaoxingtu-xianxing</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-zhexiantu-xianxing"></i> |
||||
|
<div class="name">409折线图-线性</div> |
||||
|
<div class="fontclass">.icon-zhexiantu-xianxing</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-tieta"></i> |
||||
|
<div class="name">铁塔</div> |
||||
|
<div class="fontclass">.icon-tieta</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-geshi_wendangtxt"></i> |
||||
|
<div class="name">800格式_文档txt</div> |
||||
|
<div class="fontclass">.icon-geshi_wendangtxt</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-geshi_wendangdoc"></i> |
||||
|
<div class="name">801格式_文档doc</div> |
||||
|
<div class="fontclass">.icon-geshi_wendangdoc</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-geshi_wendangpdf"></i> |
||||
|
<div class="name">807格式_文档pdf</div> |
||||
|
<div class="fontclass">.icon-geshi_wendangpdf</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-geshi_wendangxls"></i> |
||||
|
<div class="name">803格式_文档xls</div> |
||||
|
<div class="fontclass">.icon-geshi_wendangxls</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-geshi_tongyongwendang"></i> |
||||
|
<div class="name">819格式_通用文档</div> |
||||
|
<div class="fontclass">.icon-geshi_tongyongwendang</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-geshi_shipinmp"></i> |
||||
|
<div class="name">840格式_视频mp4</div> |
||||
|
<div class="fontclass">.icon-geshi_shipinmp</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-geshi_tupianjpg"></i> |
||||
|
<div class="name">860格式_图片jpg</div> |
||||
|
<div class="fontclass">.icon-geshi_tupianjpg</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-geshi_tupianpng"></i> |
||||
|
<div class="name">865格式_图片png</div> |
||||
|
<div class="fontclass">.icon-geshi_tupianpng</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-guangzhaochuanganqi"></i> |
||||
|
<div class="name">光照传感器</div> |
||||
|
<div class="fontclass">.icon-guangzhaochuanganqi</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-building"></i> |
||||
|
<div class="name">建筑</div> |
||||
|
<div class="fontclass">.icon-building</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-yanwuchuanganqi"></i> |
||||
|
<div class="name">烟雾传感器</div> |
||||
|
<div class="fontclass">.icon-yanwuchuanganqi</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-shizheng"></i> |
||||
|
<div class="name">市政</div> |
||||
|
<div class="fontclass">.icon-shizheng</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-chuanganqi"></i> |
||||
|
<div class="name">传感器</div> |
||||
|
<div class="fontclass">.icon-chuanganqi</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-WSD"></i> |
||||
|
<div class="name">温湿度传感器</div> |
||||
|
<div class="fontclass">.icon-WSD</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-yalichuanganqi"></i> |
||||
|
<div class="name">压力传感器</div> |
||||
|
<div class="fontclass">.icon-yalichuanganqi</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-yinglichuanganqi"></i> |
||||
|
<div class="name">应力传感器</div> |
||||
|
<div class="fontclass">.icon-yinglichuanganqi</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-chenjiangchuanganqi"></i> |
||||
|
<div class="name">沉降传感器</div> |
||||
|
<div class="fontclass">.icon-chenjiangchuanganqi</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-yalichuanganqi1"></i> |
||||
|
<div class="name">压力传感器</div> |
||||
|
<div class="fontclass">.icon-yalichuanganqi1</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-YWC"></i> |
||||
|
<div class="name">液位传感器</div> |
||||
|
<div class="fontclass">.icon-YWC</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-computer"></i> |
||||
|
<div class="name">computer</div> |
||||
|
<div class="fontclass">.icon-computer</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-empty"></i> |
||||
|
<div class="name">empty</div> |
||||
|
<div class="fontclass">.icon-empty</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-offline"></i> |
||||
|
<div class="name">offline</div> |
||||
|
<div class="fontclass">.icon-offline</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-daba"></i> |
||||
|
<div class="name">大坝</div> |
||||
|
<div class="fontclass">.icon-daba</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-shenbuweiyi"></i> |
||||
|
<div class="name">深部位移</div> |
||||
|
<div class="fontclass">.icon-shenbuweiyi</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-maosuochuanganqi"></i> |
||||
|
<div class="name">锚索传感器</div> |
||||
|
<div class="fontclass">.icon-maosuochuanganqi</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-yuliangchuanganqi"></i> |
||||
|
<div class="name">雨量传感器</div> |
||||
|
<div class="fontclass">.icon-yuliangchuanganqi</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-weiyiji"></i> |
||||
|
<div class="name">位移计</div> |
||||
|
<div class="fontclass">.icon-weiyiji</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-qixiangzhan_"></i> |
||||
|
<div class="name">气象站_1</div> |
||||
|
<div class="fontclass">.icon-qixiangzhan_</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc icon-shenjikeng"></i> |
||||
|
<div class="name">深基坑</div> |
||||
|
<div class="fontclass">.icon-shenjikeng</div> |
||||
|
</li> |
||||
|
|
||||
|
</ul> |
||||
|
|
||||
|
<h2 id="font-class-">font-class引用</h2> |
||||
|
<hr> |
||||
|
|
||||
|
<p>font-class是unicode使用方式的一种变种,主要是解决unicode书写不直观,语意不明确的问题。</p> |
||||
|
<p>与unicode使用方式相比,具有如下特点:</p> |
||||
|
<ul> |
||||
|
<li>兼容性良好,支持ie8+,及所有现代浏览器。</li> |
||||
|
<li>相比于unicode语意明确,书写更直观。可以很容易分辨这个icon是什么。</li> |
||||
|
<li>因为使用class来定义图标,所以当要替换图标时,只需要修改class里面的unicode引用。</li> |
||||
|
<li>不过因为本质上还是使用的字体,所以多色图标还是不支持的。</li> |
||||
|
</ul> |
||||
|
<p>使用步骤如下:</p> |
||||
|
<h3 id="-fontclass-">第一步:引入项目下面生成的fontclass代码:</h3> |
||||
|
|
||||
|
|
||||
|
<pre><code class="lang-js hljs javascript"><span class="hljs-comment"><link rel="stylesheet" type="text/css" href="./iconfont.css"></span></code></pre> |
||||
|
<h3 id="-">第二步:挑选相应图标并获取类名,应用于页面:</h3> |
||||
|
<pre><code class="lang-css hljs"><<span class="hljs-selector-tag">i</span> <span class="hljs-selector-tag">class</span>="<span class="hljs-selector-tag">sc</span> <span class="hljs-selector-tag">icon-xxx</span>"></<span class="hljs-selector-tag">i</span>></code></pre> |
||||
|
<blockquote> |
||||
|
<p>"sc"是你项目下的font-family。可以通过编辑项目查看,默认是"iconfont"。</p> |
||||
|
</blockquote> |
||||
|
</div> |
||||
|
</body> |
||||
|
</html> |
@ -0,0 +1,695 @@ |
|||||
|
|
||||
|
<!DOCTYPE html> |
||||
|
<html> |
||||
|
<head> |
||||
|
<meta charset="utf-8"/> |
||||
|
<title>IconFont</title> |
||||
|
<link rel="stylesheet" href="demo.css"> |
||||
|
<script src="iconfont.js"></script> |
||||
|
|
||||
|
<style type="text/css"> |
||||
|
.icon { |
||||
|
/* 通过设置 font-size 来改变图标大小 */ |
||||
|
width: 1em; height: 1em; |
||||
|
/* 图标和文字相邻时,垂直对齐 */ |
||||
|
vertical-align: -0.15em; |
||||
|
/* 通过设置 color 来改变 SVG 的颜色/fill */ |
||||
|
fill: currentColor; |
||||
|
/* path 和 stroke 溢出 viewBox 部分在 IE 下会显示 |
||||
|
normalize.css 中也包含这行 */ |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
|
||||
|
</style> |
||||
|
</head> |
||||
|
<body> |
||||
|
<div class="main markdown"> |
||||
|
<h1>IconFont 图标</h1> |
||||
|
<ul class="icon_lists clear"> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-liuliang"></use> |
||||
|
</svg> |
||||
|
<div class="name">流量</div> |
||||
|
<div class="fontclass">#icon-liuliang</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-iconfontditie"></use> |
||||
|
</svg> |
||||
|
<div class="name">轻轨</div> |
||||
|
<div class="fontclass">#icon-iconfontditie</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-fengsu3"></use> |
||||
|
</svg> |
||||
|
<div class="name">风速3</div> |
||||
|
<div class="fontclass">#icon-fengsu3</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-calendar"></use> |
||||
|
</svg> |
||||
|
<div class="name">calendar</div> |
||||
|
<div class="fontclass">#icon-calendar</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-box"></use> |
||||
|
</svg> |
||||
|
<div class="name">box</div> |
||||
|
<div class="fontclass">#icon-box</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-shenheshibai"></use> |
||||
|
</svg> |
||||
|
<div class="name">审核失败</div> |
||||
|
<div class="fontclass">#icon-shenheshibai</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-slope"></use> |
||||
|
</svg> |
||||
|
<div class="name">边坡</div> |
||||
|
<div class="fontclass">#icon-slope</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-icon2"></use> |
||||
|
</svg> |
||||
|
<div class="name">公路</div> |
||||
|
<div class="fontclass">#icon-icon2</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-gnsscaidian"></use> |
||||
|
</svg> |
||||
|
<div class="name">GNSS采点</div> |
||||
|
<div class="fontclass">#icon-gnsscaidian</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-chuanganqishebei"></use> |
||||
|
</svg> |
||||
|
<div class="name">传感器设备</div> |
||||
|
<div class="fontclass">#icon-chuanganqishebei</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-dianliuchuanganqi"></use> |
||||
|
</svg> |
||||
|
<div class="name">电流传感器</div> |
||||
|
<div class="fontclass">#icon-dianliuchuanganqi</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-dianyachuanganqi"></use> |
||||
|
</svg> |
||||
|
<div class="name">电压传感器</div> |
||||
|
<div class="fontclass">#icon-dianyachuanganqi</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-wenduchuanganqi"></use> |
||||
|
</svg> |
||||
|
<div class="name">温度传感器</div> |
||||
|
<div class="fontclass">#icon-wenduchuanganqi</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-xinjian"></use> |
||||
|
</svg> |
||||
|
<div class="name">新建</div> |
||||
|
<div class="fontclass">#icon-xinjian</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-handong"></use> |
||||
|
</svg> |
||||
|
<div class="name">涵洞</div> |
||||
|
<div class="fontclass">#icon-handong</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-guanwanggongcheng"></use> |
||||
|
</svg> |
||||
|
<div class="name">管网工程</div> |
||||
|
<div class="fontclass">#icon-guanwanggongcheng</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-shenhe"></use> |
||||
|
</svg> |
||||
|
<div class="name">审核</div> |
||||
|
<div class="fontclass">#icon-shenhe</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-zhihuishequ"></use> |
||||
|
</svg> |
||||
|
<div class="name">智慧城市</div> |
||||
|
<div class="fontclass">#icon-zhihuishequ</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-bianpoweiyi"></use> |
||||
|
</svg> |
||||
|
<div class="name">边坡位移</div> |
||||
|
<div class="fontclass">#icon-bianpoweiyi</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-jianzhu"></use> |
||||
|
</svg> |
||||
|
<div class="name">建筑</div> |
||||
|
<div class="fontclass">#icon-jianzhu</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-chuguan"></use> |
||||
|
</svg> |
||||
|
<div class="name">储罐</div> |
||||
|
<div class="fontclass">#icon-chuguan</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-suidao"></use> |
||||
|
</svg> |
||||
|
<div class="name">隧道</div> |
||||
|
<div class="fontclass">#icon-suidao</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-data"></use> |
||||
|
</svg> |
||||
|
<div class="name">data</div> |
||||
|
<div class="fontclass">#icon-data</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-kuangshankaicai"></use> |
||||
|
</svg> |
||||
|
<div class="name">矿山开采</div> |
||||
|
<div class="fontclass">#icon-kuangshankaicai</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-wangluo"></use> |
||||
|
</svg> |
||||
|
<div class="name">网络</div> |
||||
|
<div class="fontclass">#icon-wangluo</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-jiankong"></use> |
||||
|
</svg> |
||||
|
<div class="name">监控</div> |
||||
|
<div class="fontclass">#icon-jiankong</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-dashuju"></use> |
||||
|
</svg> |
||||
|
<div class="name">大数据</div> |
||||
|
<div class="fontclass">#icon-dashuju</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-shuju"></use> |
||||
|
</svg> |
||||
|
<div class="name">数据库</div> |
||||
|
<div class="fontclass">#icon-shuju</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-shenhechenggong"></use> |
||||
|
</svg> |
||||
|
<div class="name">审核成功</div> |
||||
|
<div class="fontclass">#icon-shenhechenggong</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-jiankong1"></use> |
||||
|
</svg> |
||||
|
<div class="name">监控</div> |
||||
|
<div class="fontclass">#icon-jiankong1</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-wangluoxitong"></use> |
||||
|
</svg> |
||||
|
<div class="name">网络系统</div> |
||||
|
<div class="fontclass">#icon-wangluoxitong</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-dingwei"></use> |
||||
|
</svg> |
||||
|
<div class="name">定位</div> |
||||
|
<div class="fontclass">#icon-dingwei</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-xitongyunzhuanqingkuang"></use> |
||||
|
</svg> |
||||
|
<div class="name">系统运转情况</div> |
||||
|
<div class="fontclass">#icon-xitongyunzhuanqingkuang</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-chakan"></use> |
||||
|
</svg> |
||||
|
<div class="name">查看</div> |
||||
|
<div class="fontclass">#icon-chakan</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-lianjie"></use> |
||||
|
</svg> |
||||
|
<div class="name">链接</div> |
||||
|
<div class="fontclass">#icon-lianjie</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-shujudaochu-01"></use> |
||||
|
</svg> |
||||
|
<div class="name">数据导出-01</div> |
||||
|
<div class="fontclass">#icon-shujudaochu-01</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-xitongzhuangtai"></use> |
||||
|
</svg> |
||||
|
<div class="name">系统状态</div> |
||||
|
<div class="fontclass">#icon-xitongzhuangtai</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-xiaofeimingxidan"></use> |
||||
|
</svg> |
||||
|
<div class="name">消费明细单</div> |
||||
|
<div class="fontclass">#icon-xiaofeimingxidan</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-SQLshenhe"></use> |
||||
|
</svg> |
||||
|
<div class="name">SQL审核</div> |
||||
|
<div class="fontclass">#icon-SQLshenhe</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-aislogo"></use> |
||||
|
</svg> |
||||
|
<div class="name">aislogo</div> |
||||
|
<div class="fontclass">#icon-aislogo</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-qiao"></use> |
||||
|
</svg> |
||||
|
<div class="name">桥</div> |
||||
|
<div class="fontclass">#icon-qiao</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-tashiqizhongji"></use> |
||||
|
</svg> |
||||
|
<div class="name">塔式起重机</div> |
||||
|
<div class="fontclass">#icon-tashiqizhongji</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-dwggeshi"></use> |
||||
|
</svg> |
||||
|
<div class="name">dwg格式</div> |
||||
|
<div class="fontclass">#icon-dwggeshi</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-luyouqi"></use> |
||||
|
</svg> |
||||
|
<div class="name">路由器</div> |
||||
|
<div class="fontclass">#icon-luyouqi</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-anzhuangshigong-xianxing"></use> |
||||
|
</svg> |
||||
|
<div class="name">244安装、施工-线性</div> |
||||
|
<div class="fontclass">#icon-anzhuangshigong-xianxing</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-shaixuanguolv"></use> |
||||
|
</svg> |
||||
|
<div class="name">245筛选过滤</div> |
||||
|
<div class="fontclass">#icon-shaixuanguolv</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-anzhuangshigong"></use> |
||||
|
</svg> |
||||
|
<div class="name">244安装、施工</div> |
||||
|
<div class="fontclass">#icon-anzhuangshigong</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-tiaoxingtu-xianxing"></use> |
||||
|
</svg> |
||||
|
<div class="name">408条形图-线性</div> |
||||
|
<div class="fontclass">#icon-tiaoxingtu-xianxing</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-zhexiantu-xianxing"></use> |
||||
|
</svg> |
||||
|
<div class="name">409折线图-线性</div> |
||||
|
<div class="fontclass">#icon-zhexiantu-xianxing</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-tieta"></use> |
||||
|
</svg> |
||||
|
<div class="name">铁塔</div> |
||||
|
<div class="fontclass">#icon-tieta</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-geshi_wendangtxt"></use> |
||||
|
</svg> |
||||
|
<div class="name">800格式_文档txt</div> |
||||
|
<div class="fontclass">#icon-geshi_wendangtxt</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-geshi_wendangdoc"></use> |
||||
|
</svg> |
||||
|
<div class="name">801格式_文档doc</div> |
||||
|
<div class="fontclass">#icon-geshi_wendangdoc</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-geshi_wendangpdf"></use> |
||||
|
</svg> |
||||
|
<div class="name">807格式_文档pdf</div> |
||||
|
<div class="fontclass">#icon-geshi_wendangpdf</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-geshi_wendangxls"></use> |
||||
|
</svg> |
||||
|
<div class="name">803格式_文档xls</div> |
||||
|
<div class="fontclass">#icon-geshi_wendangxls</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-geshi_tongyongwendang"></use> |
||||
|
</svg> |
||||
|
<div class="name">819格式_通用文档</div> |
||||
|
<div class="fontclass">#icon-geshi_tongyongwendang</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-geshi_shipinmp"></use> |
||||
|
</svg> |
||||
|
<div class="name">840格式_视频mp4</div> |
||||
|
<div class="fontclass">#icon-geshi_shipinmp</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-geshi_tupianjpg"></use> |
||||
|
</svg> |
||||
|
<div class="name">860格式_图片jpg</div> |
||||
|
<div class="fontclass">#icon-geshi_tupianjpg</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-geshi_tupianpng"></use> |
||||
|
</svg> |
||||
|
<div class="name">865格式_图片png</div> |
||||
|
<div class="fontclass">#icon-geshi_tupianpng</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-guangzhaochuanganqi"></use> |
||||
|
</svg> |
||||
|
<div class="name">光照传感器</div> |
||||
|
<div class="fontclass">#icon-guangzhaochuanganqi</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-building"></use> |
||||
|
</svg> |
||||
|
<div class="name">建筑</div> |
||||
|
<div class="fontclass">#icon-building</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-yanwuchuanganqi"></use> |
||||
|
</svg> |
||||
|
<div class="name">烟雾传感器</div> |
||||
|
<div class="fontclass">#icon-yanwuchuanganqi</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-shizheng"></use> |
||||
|
</svg> |
||||
|
<div class="name">市政</div> |
||||
|
<div class="fontclass">#icon-shizheng</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-chuanganqi"></use> |
||||
|
</svg> |
||||
|
<div class="name">传感器</div> |
||||
|
<div class="fontclass">#icon-chuanganqi</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-WSD"></use> |
||||
|
</svg> |
||||
|
<div class="name">温湿度传感器</div> |
||||
|
<div class="fontclass">#icon-WSD</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-yalichuanganqi"></use> |
||||
|
</svg> |
||||
|
<div class="name">压力传感器</div> |
||||
|
<div class="fontclass">#icon-yalichuanganqi</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-yinglichuanganqi"></use> |
||||
|
</svg> |
||||
|
<div class="name">应力传感器</div> |
||||
|
<div class="fontclass">#icon-yinglichuanganqi</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-chenjiangchuanganqi"></use> |
||||
|
</svg> |
||||
|
<div class="name">沉降传感器</div> |
||||
|
<div class="fontclass">#icon-chenjiangchuanganqi</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-yalichuanganqi1"></use> |
||||
|
</svg> |
||||
|
<div class="name">压力传感器</div> |
||||
|
<div class="fontclass">#icon-yalichuanganqi1</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-YWC"></use> |
||||
|
</svg> |
||||
|
<div class="name">液位传感器</div> |
||||
|
<div class="fontclass">#icon-YWC</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-computer"></use> |
||||
|
</svg> |
||||
|
<div class="name">computer</div> |
||||
|
<div class="fontclass">#icon-computer</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-empty"></use> |
||||
|
</svg> |
||||
|
<div class="name">empty</div> |
||||
|
<div class="fontclass">#icon-empty</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-offline"></use> |
||||
|
</svg> |
||||
|
<div class="name">offline</div> |
||||
|
<div class="fontclass">#icon-offline</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-daba"></use> |
||||
|
</svg> |
||||
|
<div class="name">大坝</div> |
||||
|
<div class="fontclass">#icon-daba</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-shenbuweiyi"></use> |
||||
|
</svg> |
||||
|
<div class="name">深部位移</div> |
||||
|
<div class="fontclass">#icon-shenbuweiyi</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-maosuochuanganqi"></use> |
||||
|
</svg> |
||||
|
<div class="name">锚索传感器</div> |
||||
|
<div class="fontclass">#icon-maosuochuanganqi</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-yuliangchuanganqi"></use> |
||||
|
</svg> |
||||
|
<div class="name">雨量传感器</div> |
||||
|
<div class="fontclass">#icon-yuliangchuanganqi</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-weiyiji"></use> |
||||
|
</svg> |
||||
|
<div class="name">位移计</div> |
||||
|
<div class="fontclass">#icon-weiyiji</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-qixiangzhan_"></use> |
||||
|
</svg> |
||||
|
<div class="name">气象站_1</div> |
||||
|
<div class="fontclass">#icon-qixiangzhan_</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-shenjikeng"></use> |
||||
|
</svg> |
||||
|
<div class="name">深基坑</div> |
||||
|
<div class="fontclass">#icon-shenjikeng</div> |
||||
|
</li> |
||||
|
|
||||
|
</ul> |
||||
|
|
||||
|
|
||||
|
<h2 id="symbol-">symbol引用</h2> |
||||
|
<hr> |
||||
|
|
||||
|
<p>这是一种全新的使用方式,应该说这才是未来的主流,也是平台目前推荐的用法。相关介绍可以参考这篇<a href="">文章</a> |
||||
|
这种用法其实是做了一个svg的集合,与另外两种相比具有如下特点:</p> |
||||
|
<ul> |
||||
|
<li>支持多色图标了,不再受单色限制。</li> |
||||
|
<li>通过一些技巧,支持像字体那样,通过<code>font-size</code>,<code>color</code>来调整样式。</li> |
||||
|
<li>兼容性较差,支持 ie9+,及现代浏览器。</li> |
||||
|
<li>浏览器渲染svg的性能一般,还不如png。</li> |
||||
|
</ul> |
||||
|
<p>使用步骤如下:</p> |
||||
|
<h3 id="-symbol-">第一步:引入项目下面生成的symbol代码:</h3> |
||||
|
<pre><code class="lang-js hljs javascript"><span class="hljs-comment"><script src="./iconfont.js"></script></span></code></pre> |
||||
|
<h3 id="-css-">第二步:加入通用css代码(引入一次就行):</h3> |
||||
|
<pre><code class="lang-js hljs javascript"><style type=<span class="hljs-string">"text/css"</span>> |
||||
|
.icon { |
||||
|
width: <span class="hljs-number">1</span>em; height: <span class="hljs-number">1</span>em; |
||||
|
vertical-align: <span class="hljs-number">-0.15</span>em; |
||||
|
fill: currentColor; |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
<<span class="hljs-regexp">/style></span></code></pre> |
||||
|
<h3 id="-">第三步:挑选相应图标并获取类名,应用于页面:</h3> |
||||
|
<pre><code class="lang-js hljs javascript"><svg <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"icon"</span> aria-hidden=<span class="hljs-string">"true"</span>><span class="xml"><span class="hljs-tag"> |
||||
|
<<span class="hljs-name">use</span> <span class="hljs-attr">xlink:href</span>=<span class="hljs-string">"#icon-xxx"</span>></span><span class="hljs-tag"></<span class="hljs-name">use</span>></span> |
||||
|
</span><<span class="hljs-regexp">/svg> |
||||
|
</span></code></pre> |
||||
|
</div> |
||||
|
</body> |
||||
|
</html> |
@ -0,0 +1,552 @@ |
|||||
|
|
||||
|
<!DOCTYPE html> |
||||
|
<html> |
||||
|
<head> |
||||
|
<meta charset="utf-8"/> |
||||
|
<title>IconFont</title> |
||||
|
<link rel="stylesheet" href="demo.css"> |
||||
|
|
||||
|
<style type="text/css"> |
||||
|
|
||||
|
@font-face {font-family: "sc"; |
||||
|
src: url('iconfont.eot'); /* IE9*/ |
||||
|
src: url('iconfont.eot#iefix') format('embedded-opentype'), /* IE6-IE8 */ |
||||
|
url('iconfont.woff') format('woff'), /* chrome, firefox */ |
||||
|
url('iconfont.ttf') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/ |
||||
|
url('iconfont.svg#sc') format('svg'); /* iOS 4.1- */ |
||||
|
} |
||||
|
|
||||
|
.sc { |
||||
|
font-family:"sc" !important; |
||||
|
font-size:16px; |
||||
|
font-style:normal; |
||||
|
-webkit-font-smoothing: antialiased; |
||||
|
-webkit-text-stroke-width: 0.2px; |
||||
|
-moz-osx-font-smoothing: grayscale; |
||||
|
} |
||||
|
|
||||
|
</style> |
||||
|
</head> |
||||
|
<body> |
||||
|
<div class="main markdown"> |
||||
|
<h1>IconFont 图标</h1> |
||||
|
<ul class="icon_lists clear"> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">流量</div> |
||||
|
<div class="code">&#xe602;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">轻轨</div> |
||||
|
<div class="code">&#xe66f;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">风速3</div> |
||||
|
<div class="code">&#xe635;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">calendar</div> |
||||
|
<div class="code">&#xe74a;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">box</div> |
||||
|
<div class="code">&#xe6cb;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">审核失败</div> |
||||
|
<div class="code">&#xe61d;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">边坡</div> |
||||
|
<div class="code">&#xe676;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">公路</div> |
||||
|
<div class="code">&#xe607;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">GNSS采点</div> |
||||
|
<div class="code">&#xe825;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">传感器设备</div> |
||||
|
<div class="code">&#xe612;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">电流传感器</div> |
||||
|
<div class="code">&#xe62c;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">电压传感器</div> |
||||
|
<div class="code">&#xe62f;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">温度传感器</div> |
||||
|
<div class="code">&#xe637;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">新建</div> |
||||
|
<div class="code">&#xe61f;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">涵洞</div> |
||||
|
<div class="code">&#xe89b;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">管网工程</div> |
||||
|
<div class="code">&#xe646;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">审核</div> |
||||
|
<div class="code">&#xe639;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">智慧城市</div> |
||||
|
<div class="code">&#xe600;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">边坡位移</div> |
||||
|
<div class="code">&#xe60a;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">建筑</div> |
||||
|
<div class="code">&#xe65f;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">储罐</div> |
||||
|
<div class="code">&#xe636;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">隧道</div> |
||||
|
<div class="code">&#xe61e;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">data</div> |
||||
|
<div class="code">&#xe757;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">矿山开采</div> |
||||
|
<div class="code">&#xe608;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">网络</div> |
||||
|
<div class="code">&#xe617;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">监控</div> |
||||
|
<div class="code">&#xe619;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">大数据</div> |
||||
|
<div class="code">&#xe61a;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">数据库</div> |
||||
|
<div class="code">&#xe61b;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">审核成功</div> |
||||
|
<div class="code">&#xe627;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">监控</div> |
||||
|
<div class="code">&#xe620;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">网络系统</div> |
||||
|
<div class="code">&#xe62e;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">定位</div> |
||||
|
<div class="code">&#xe630;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">系统运转情况</div> |
||||
|
<div class="code">&#xe631;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">查看</div> |
||||
|
<div class="code">&#xe63e;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">链接</div> |
||||
|
<div class="code">&#xe63f;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">数据导出-01</div> |
||||
|
<div class="code">&#xe640;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">系统状态</div> |
||||
|
<div class="code">&#xe642;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">消费明细单</div> |
||||
|
<div class="code">&#xe643;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">SQL审核</div> |
||||
|
<div class="code">&#xe645;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">aislogo</div> |
||||
|
<div class="code">&#xe648;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">桥</div> |
||||
|
<div class="code">&#xe715;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">塔式起重机</div> |
||||
|
<div class="code">&#xe615;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">dwg格式</div> |
||||
|
<div class="code">&#xe82b;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">路由器</div> |
||||
|
<div class="code">&#xe603;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">244安装、施工-线性</div> |
||||
|
<div class="code">&#xe8d6;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">245筛选过滤</div> |
||||
|
<div class="code">&#xe8d7;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">244安装、施工</div> |
||||
|
<div class="code">&#xe8d8;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">408条形图-线性</div> |
||||
|
<div class="code">&#xe904;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">409折线图-线性</div> |
||||
|
<div class="code">&#xe906;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">铁塔</div> |
||||
|
<div class="code">&#xe605;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">800格式_文档txt</div> |
||||
|
<div class="code">&#xe6b8;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">801格式_文档doc</div> |
||||
|
<div class="code">&#xe6b9;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">807格式_文档pdf</div> |
||||
|
<div class="code">&#xe6bc;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">803格式_文档xls</div> |
||||
|
<div class="code">&#xe6be;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">819格式_通用文档</div> |
||||
|
<div class="code">&#xe6c0;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">840格式_视频mp4</div> |
||||
|
<div class="code">&#xe6c8;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">860格式_图片jpg</div> |
||||
|
<div class="code">&#xe6cc;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">865格式_图片png</div> |
||||
|
<div class="code">&#xe6ce;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">光照传感器</div> |
||||
|
<div class="code">&#xe638;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">建筑</div> |
||||
|
<div class="code">&#xe61c;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">烟雾传感器</div> |
||||
|
<div class="code">&#xe610;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">市政</div> |
||||
|
<div class="code">&#xe6ca;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">传感器</div> |
||||
|
<div class="code">&#xe60f;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">温湿度传感器</div> |
||||
|
<div class="code">&#xe697;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">压力传感器</div> |
||||
|
<div class="code">&#xe60e;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">应力传感器</div> |
||||
|
<div class="code">&#xe611;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">沉降传感器</div> |
||||
|
<div class="code">&#xe601;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">压力传感器</div> |
||||
|
<div class="code">&#xe606;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">液位传感器</div> |
||||
|
<div class="code">&#xe699;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">computer</div> |
||||
|
<div class="code">&#xe6eb;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">empty</div> |
||||
|
<div class="code">&#xe6f7;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">offline</div> |
||||
|
<div class="code">&#xe712;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">大坝</div> |
||||
|
<div class="code">&#xe632;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">深部位移</div> |
||||
|
<div class="code">&#xe613;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">锚索传感器</div> |
||||
|
<div class="code">&#xe614;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">雨量传感器</div> |
||||
|
<div class="code">&#xe616;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">位移计</div> |
||||
|
<div class="code">&#xe618;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">气象站_1</div> |
||||
|
<div class="code">&#xe60d;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li> |
||||
|
<i class="icon sc"></i> |
||||
|
<div class="name">深基坑</div> |
||||
|
<div class="code">&#xe62a;</div> |
||||
|
</li> |
||||
|
|
||||
|
</ul> |
||||
|
<h2 id="unicode-">unicode引用</h2> |
||||
|
<hr> |
||||
|
|
||||
|
<p>unicode是字体在网页端最原始的应用方式,特点是:</p> |
||||
|
<ul> |
||||
|
<li>兼容性最好,支持ie6+,及所有现代浏览器。</li> |
||||
|
<li>支持按字体的方式去动态调整图标大小,颜色等等。</li> |
||||
|
<li>但是因为是字体,所以不支持多色。只能使用平台里单色的图标,就算项目里有多色图标也会自动去色。</li> |
||||
|
</ul> |
||||
|
<blockquote> |
||||
|
<p>注意:新版iconfont支持多色图标,这些多色图标在unicode模式下将不能使用,如果有需求建议使用symbol的引用方式</p> |
||||
|
</blockquote> |
||||
|
<p>unicode使用步骤如下:</p> |
||||
|
<h3 id="-font-face">第一步:拷贝项目下面生成的font-face</h3> |
||||
|
<pre><code class="lang-js hljs javascript">@font-face { |
||||
|
font-family: <span class="hljs-string">'sc'</span>; |
||||
|
src: url(<span class="hljs-string">'iconfont.eot'</span>); |
||||
|
src: url(<span class="hljs-string">'iconfont.eot?#iefix'</span>) format(<span class="hljs-string">'embedded-opentype'</span>), |
||||
|
url(<span class="hljs-string">'iconfont.woff'</span>) format(<span class="hljs-string">'woff'</span>), |
||||
|
url(<span class="hljs-string">'iconfont.ttf'</span>) format(<span class="hljs-string">'truetype'</span>), |
||||
|
url(<span class="hljs-string">'iconfont.svg#sc'</span>) format(<span class="hljs-string">'svg'</span>); |
||||
|
} |
||||
|
</code></pre> |
||||
|
<h3 id="-iconfont-">第二步:定义使用iconfont的样式</h3> |
||||
|
<pre><code class="lang-js hljs javascript">.sc{ |
||||
|
font-family:<span class="hljs-string">"sc"</span> !important; |
||||
|
font-size:<span class="hljs-number">16</span>px;font-style:normal; |
||||
|
-webkit-font-smoothing: antialiased; |
||||
|
-webkit-text-stroke-width: <span class="hljs-number">0.2</span>px; |
||||
|
-moz-osx-font-smoothing: grayscale; |
||||
|
} |
||||
|
</code></pre> |
||||
|
<h3 id="-">第三步:挑选相应图标并获取字体编码,应用于页面</h3> |
||||
|
<pre><code class="lang-js hljs javascript"><i <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"sc"</span>>&#x33;<span class="xml"><span class="hljs-tag"></<span class="hljs-name">i</span>></span></span></code></pre> |
||||
|
|
||||
|
<blockquote> |
||||
|
<p>"sc"是你项目下的font-family。可以通过编辑项目查看,默认是"iconfont"。</p> |
||||
|
</blockquote> |
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
</body> |
||||
|
</html> |
After Width: | Height: | Size: 148 KiB |
@ -0,0 +1,521 @@ |
|||||
|
|
||||
|
@font-face {font-family: "anticon"; |
||||
|
src: url('iconfont.eot?t=1494480257283'); /* IE9*/ |
||||
|
src: url('iconfont.eot?t=1494480257283#iefix') format('embedded-opentype'), /* IE6-IE8 */ |
||||
|
url('iconfont.woff?t=1494480257283') format('woff'), /* chrome, firefox */ |
||||
|
url('iconfont.ttf?t=1494480257283') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/ |
||||
|
url('iconfont.svg?t=1494480257283#anticon') format('svg'); /* iOS 4.1- */ |
||||
|
} |
||||
|
|
||||
|
.anticon { |
||||
|
font-family:"anticon" !important; |
||||
|
font-size:16px; |
||||
|
font-style:normal; |
||||
|
-webkit-font-smoothing: antialiased; |
||||
|
-moz-osx-font-smoothing: grayscale; |
||||
|
} |
||||
|
|
||||
|
.icon-stepforward:before { content: "\e600"; } |
||||
|
|
||||
|
.icon-stepbackward:before { content: "\e601"; } |
||||
|
|
||||
|
.icon-forward:before { content: "\e602"; } |
||||
|
|
||||
|
.icon-banckward:before { content: "\e603"; } |
||||
|
|
||||
|
.icon-caretright:before { content: "\e604"; } |
||||
|
|
||||
|
.icon-caretleft:before { content: "\e605"; } |
||||
|
|
||||
|
.icon-caretdown:before { content: "\e606"; } |
||||
|
|
||||
|
.icon-caretup:before { content: "\e607"; } |
||||
|
|
||||
|
.icon-rightcircle:before { content: "\e608"; } |
||||
|
|
||||
|
.icon-leftcircle:before { content: "\e609"; } |
||||
|
|
||||
|
.icon-upcircle:before { content: "\e60a"; } |
||||
|
|
||||
|
.icon-downcircle:before { content: "\e60b"; } |
||||
|
|
||||
|
.icon-rightcircleo:before { content: "\e60c"; } |
||||
|
|
||||
|
.icon-leftcircleo:before { content: "\e60d"; } |
||||
|
|
||||
|
.icon-upcircleo:before { content: "\e60e"; } |
||||
|
|
||||
|
.icon-downcircleo:before { content: "\e60f"; } |
||||
|
|
||||
|
.icon-verticleleft:before { content: "\e610"; } |
||||
|
|
||||
|
.icon-verticleright:before { content: "\e611"; } |
||||
|
|
||||
|
.icon-rollback:before { content: "\e612"; } |
||||
|
|
||||
|
.icon-retweet:before { content: "\e613"; } |
||||
|
|
||||
|
.icon-shrink:before { content: "\e614"; } |
||||
|
|
||||
|
.icon-arrowsalt:before { content: "\e615"; } |
||||
|
|
||||
|
.icon-doubleright:before { content: "\e617"; } |
||||
|
|
||||
|
.icon-doubleleft:before { content: "\e618"; } |
||||
|
|
||||
|
.icon-arrowdown:before { content: "\e619"; } |
||||
|
|
||||
|
.icon-arrowup:before { content: "\e61a"; } |
||||
|
|
||||
|
.icon-arrowright:before { content: "\e61b"; } |
||||
|
|
||||
|
.icon-arrowleft:before { content: "\e61c"; } |
||||
|
|
||||
|
.icon-down:before { content: "\e61d"; } |
||||
|
|
||||
|
.icon-up:before { content: "\e61e"; } |
||||
|
|
||||
|
.icon-right:before { content: "\e61f"; } |
||||
|
|
||||
|
.icon-left:before { content: "\e620"; } |
||||
|
|
||||
|
.icon-minussquareo:before { content: "\e621"; } |
||||
|
|
||||
|
.icon-minuscircle:before { content: "\e622"; } |
||||
|
|
||||
|
.icon-minuscircleo:before { content: "\e623"; } |
||||
|
|
||||
|
.icon-minus:before { content: "\e624"; } |
||||
|
|
||||
|
.icon-pluscircleo:before { content: "\e625"; } |
||||
|
|
||||
|
.icon-pluscircle:before { content: "\e626"; } |
||||
|
|
||||
|
.icon-plus:before { content: "\e627"; } |
||||
|
|
||||
|
.icon-infocirlce:before { content: "\e628"; } |
||||
|
|
||||
|
.icon-infocirlceo:before { content: "\e629"; } |
||||
|
|
||||
|
.icon-info:before { content: "\e62a"; } |
||||
|
|
||||
|
.icon-exclamation:before { content: "\e62b"; } |
||||
|
|
||||
|
.icon-exclamationcircle:before { content: "\e62c"; } |
||||
|
|
||||
|
.icon-exclamationcircleo:before { content: "\e62d"; } |
||||
|
|
||||
|
.icon-closecircle:before { content: "\e62e"; } |
||||
|
|
||||
|
.icon-closecircleo:before { content: "\e62f"; } |
||||
|
|
||||
|
.icon-checkcircle:before { content: "\e630"; } |
||||
|
|
||||
|
.icon-checkcircleo:before { content: "\e631"; } |
||||
|
|
||||
|
.icon-check:before { content: "\e632"; } |
||||
|
|
||||
|
.icon-close:before { content: "\e633"; } |
||||
|
|
||||
|
.icon-customerservice:before { content: "\e634"; } |
||||
|
|
||||
|
.icon-creditcard:before { content: "\e635"; } |
||||
|
|
||||
|
.icon-codesquareo:before { content: "\e636"; } |
||||
|
|
||||
|
.icon-book:before { content: "\e637"; } |
||||
|
|
||||
|
.icon-barschart:before { content: "\e638"; } |
||||
|
|
||||
|
.icon-bars:before { content: "\e639"; } |
||||
|
|
||||
|
.icon-question:before { content: "\e63a"; } |
||||
|
|
||||
|
.icon-questioncircle:before { content: "\e63b"; } |
||||
|
|
||||
|
.icon-questioncircleo:before { content: "\e63c"; } |
||||
|
|
||||
|
.icon-pause:before { content: "\e63d"; } |
||||
|
|
||||
|
.icon-pausecircle:before { content: "\e63e"; } |
||||
|
|
||||
|
.icon-pausecircleo:before { content: "\e63f"; } |
||||
|
|
||||
|
.icon-clockcircle:before { content: "\e640"; } |
||||
|
|
||||
|
.icon-clockcircleo:before { content: "\e641"; } |
||||
|
|
||||
|
.icon-swap:before { content: "\e642"; } |
||||
|
|
||||
|
.icon-swapleft:before { content: "\e643"; } |
||||
|
|
||||
|
.icon-swapright:before { content: "\e644"; } |
||||
|
|
||||
|
.icon-plussquareo:before { content: "\e645"; } |
||||
|
|
||||
|
.icon-frown:before { content: "\e646"; } |
||||
|
|
||||
|
.icon-menufold:before { content: "\e658"; } |
||||
|
|
||||
|
.icon-mail:before { content: "\e659"; } |
||||
|
|
||||
|
.icon-link:before { content: "\e65b"; } |
||||
|
|
||||
|
.icon-areachart:before { content: "\e65c"; } |
||||
|
|
||||
|
.icon-linechart:before { content: "\e65d"; } |
||||
|
|
||||
|
.icon-home:before { content: "\e65e"; } |
||||
|
|
||||
|
.icon-laptop:before { content: "\e65f"; } |
||||
|
|
||||
|
.icon-star:before { content: "\e660"; } |
||||
|
|
||||
|
.icon-staro:before { content: "\e661"; } |
||||
|
|
||||
|
.icon-filter:before { content: "\e663"; } |
||||
|
|
||||
|
.icon-meho:before { content: "\e666"; } |
||||
|
|
||||
|
.icon-meh:before { content: "\e667"; } |
||||
|
|
||||
|
.icon-shoppingcart:before { content: "\e668"; } |
||||
|
|
||||
|
.icon-save:before { content: "\e669"; } |
||||
|
|
||||
|
.icon-user:before { content: "\e66a"; } |
||||
|
|
||||
|
.icon-videocamera:before { content: "\e66b"; } |
||||
|
|
||||
|
.icon-totop:before { content: "\e66c"; } |
||||
|
|
||||
|
.icon-team:before { content: "\e66d"; } |
||||
|
|
||||
|
.icon-sharealt:before { content: "\e671"; } |
||||
|
|
||||
|
.icon-setting:before { content: "\e672"; } |
||||
|
|
||||
|
.icon-picture:before { content: "\e674"; } |
||||
|
|
||||
|
.icon-phone:before { content: "\e675"; } |
||||
|
|
||||
|
.icon-paperclip:before { content: "\e676"; } |
||||
|
|
||||
|
.icon-notification:before { content: "\e677"; } |
||||
|
|
||||
|
.icon-menuunfold:before { content: "\e679"; } |
||||
|
|
||||
|
.icon-inbox:before { content: "\e67a"; } |
||||
|
|
||||
|
.icon-lock:before { content: "\e67b"; } |
||||
|
|
||||
|
.icon-qrcode:before { content: "\e67c"; } |
||||
|
|
||||
|
.icon-tags:before { content: "\e67d"; } |
||||
|
|
||||
|
.icon-tagso:before { content: "\e67e"; } |
||||
|
|
||||
|
.icon-cloudo:before { content: "\e67f"; } |
||||
|
|
||||
|
.icon-cloud:before { content: "\e680"; } |
||||
|
|
||||
|
.icon-cloudupload:before { content: "\e681"; } |
||||
|
|
||||
|
.icon-clouddownload:before { content: "\e682"; } |
||||
|
|
||||
|
.icon-clouddownloado:before { content: "\e683"; } |
||||
|
|
||||
|
.icon-clouduploado:before { content: "\e684"; } |
||||
|
|
||||
|
.icon-enviroment:before { content: "\e685"; } |
||||
|
|
||||
|
.icon-enviromento:before { content: "\e686"; } |
||||
|
|
||||
|
.icon-eye:before { content: "\e687"; } |
||||
|
|
||||
|
.icon-eyeo:before { content: "\e688"; } |
||||
|
|
||||
|
.icon-camera:before { content: "\e689"; } |
||||
|
|
||||
|
.icon-camerao:before { content: "\e68a"; } |
||||
|
|
||||
|
.icon-windows:before { content: "\e68b"; } |
||||
|
|
||||
|
.icon-export2:before { content: "\e690"; } |
||||
|
|
||||
|
.icon-export:before { content: "\e691"; } |
||||
|
|
||||
|
.icon-circledowno:before { content: "\e693"; } |
||||
|
|
||||
|
.icon-circledown:before { content: "\e694"; } |
||||
|
|
||||
|
.icon-hdd:before { content: "\e69a"; } |
||||
|
|
||||
|
.icon-ie:before { content: "\e69b"; } |
||||
|
|
||||
|
.icon-delete:before { content: "\e69f"; } |
||||
|
|
||||
|
.icon-enter:before { content: "\e6a0"; } |
||||
|
|
||||
|
.icon-pushpino:before { content: "\e6a1"; } |
||||
|
|
||||
|
.icon-pushpin:before { content: "\e6a2"; } |
||||
|
|
||||
|
.icon-heart:before { content: "\e6a3"; } |
||||
|
|
||||
|
.icon-hearto:before { content: "\e6a4"; } |
||||
|
|
||||
|
.icon-smile-circle:before { content: "\e6a7"; } |
||||
|
|
||||
|
.icon-smileo:before { content: "\e6a8"; } |
||||
|
|
||||
|
.icon-frowno:before { content: "\e6a9"; } |
||||
|
|
||||
|
.icon-calculator:before { content: "\e6aa"; } |
||||
|
|
||||
|
.icon-chrome:before { content: "\e6ac"; } |
||||
|
|
||||
|
.icon-github:before { content: "\e6ad"; } |
||||
|
|
||||
|
.icon-iconfontdesktop:before { content: "\e6b4"; } |
||||
|
|
||||
|
.icon-caretcircleoup:before { content: "\e6b5"; } |
||||
|
|
||||
|
.icon-upload:before { content: "\e6b6"; } |
||||
|
|
||||
|
.icon-download:before { content: "\e6b7"; } |
||||
|
|
||||
|
.icon-piechart:before { content: "\e6b8"; } |
||||
|
|
||||
|
.icon-lock1:before { content: "\e6b9"; } |
||||
|
|
||||
|
.icon-unlock:before { content: "\e6ba"; } |
||||
|
|
||||
|
.icon-windowso:before { content: "\e6bc"; } |
||||
|
|
||||
|
.icon-dotchart:before { content: "\e6bd"; } |
||||
|
|
||||
|
.icon-barchart:before { content: "\e6be"; } |
||||
|
|
||||
|
.icon-codesquare:before { content: "\e6bf"; } |
||||
|
|
||||
|
.icon-plussquare:before { content: "\e6c0"; } |
||||
|
|
||||
|
.icon-minussquare:before { content: "\e6c1"; } |
||||
|
|
||||
|
.icon-closesquare:before { content: "\e6c2"; } |
||||
|
|
||||
|
.icon-closesquareo:before { content: "\e6c3"; } |
||||
|
|
||||
|
.icon-checksquare:before { content: "\e6c4"; } |
||||
|
|
||||
|
.icon-checksquareo:before { content: "\e6c5"; } |
||||
|
|
||||
|
.icon-fastbackward:before { content: "\e6c6"; } |
||||
|
|
||||
|
.icon-fastforward:before { content: "\e6c7"; } |
||||
|
|
||||
|
.icon-upsquare:before { content: "\e6c8"; } |
||||
|
|
||||
|
.icon-downsquare:before { content: "\e6c9"; } |
||||
|
|
||||
|
.icon-leftsquare:before { content: "\e6ca"; } |
||||
|
|
||||
|
.icon-rightsquare:before { content: "\e6cb"; } |
||||
|
|
||||
|
.icon-rightsquareo:before { content: "\e6cc"; } |
||||
|
|
||||
|
.icon-leftsquareo:before { content: "\e6cd"; } |
||||
|
|
||||
|
.icon-down-square-o:before { content: "\e6ce"; } |
||||
|
|
||||
|
.icon-up-square-o:before { content: "\e6cf"; } |
||||
|
|
||||
|
.icon-play:before { content: "\e6d0"; } |
||||
|
|
||||
|
.icon-playcircleo:before { content: "\e6d1"; } |
||||
|
|
||||
|
.icon-tag:before { content: "\e6d2"; } |
||||
|
|
||||
|
.icon-tago:before { content: "\e6d3"; } |
||||
|
|
||||
|
.icon-addfile:before { content: "\e910"; } |
||||
|
|
||||
|
.icon-folder1:before { content: "\e662"; } |
||||
|
|
||||
|
.icon-file1:before { content: "\e664"; } |
||||
|
|
||||
|
.icon-switcher:before { content: "\e913"; } |
||||
|
|
||||
|
.icon-addfolder:before { content: "\e914"; } |
||||
|
|
||||
|
.icon-folderopen:before { content: "\e699"; } |
||||
|
|
||||
|
.icon-search1:before { content: "\e670"; } |
||||
|
|
||||
|
.icon-ellipsis1:before { content: "\e647"; } |
||||
|
|
||||
|
.icon-calendar:before { content: "\e6bb"; } |
||||
|
|
||||
|
.icon-filetext1:before { content: "\e698"; } |
||||
|
|
||||
|
.icon-copy1:before { content: "\e648"; } |
||||
|
|
||||
|
.icon-jpgfile1:before { content: "\e69c"; } |
||||
|
|
||||
|
.icon-pdffile1:before { content: "\e6b3"; } |
||||
|
|
||||
|
.icon-exclefile1:before { content: "\e6b0"; } |
||||
|
|
||||
|
.icon-pptfile1:before { content: "\e6b1"; } |
||||
|
|
||||
|
.icon-unknowfile1:before { content: "\e6af"; } |
||||
|
|
||||
|
.icon-wordfile1:before { content: "\e6b2"; } |
||||
|
|
||||
|
.icon-dingding:before { content: "\e923"; } |
||||
|
|
||||
|
.icon-dingding-o:before { content: "\e925"; } |
||||
|
|
||||
|
.icon-mobile1:before { content: "\e678"; } |
||||
|
|
||||
|
.icon-tablet1:before { content: "\e66e"; } |
||||
|
|
||||
|
.icon-bells:before { content: "\e64e"; } |
||||
|
|
||||
|
.icon-disconnect:before { content: "\e64f"; } |
||||
|
|
||||
|
.icon-database:before { content: "\e650"; } |
||||
|
|
||||
|
.icon-barcode:before { content: "\e652"; } |
||||
|
|
||||
|
.icon-hourglass:before { content: "\e653"; } |
||||
|
|
||||
|
.icon-key:before { content: "\e654"; } |
||||
|
|
||||
|
.icon-flag:before { content: "\e655"; } |
||||
|
|
||||
|
.icon-layout:before { content: "\e656"; } |
||||
|
|
||||
|
.icon-printer:before { content: "\e673"; } |
||||
|
|
||||
|
.icon-USB:before { content: "\e6d7"; } |
||||
|
|
||||
|
.icon-skin:before { content: "\e6d8"; } |
||||
|
|
||||
|
.icon-tool:before { content: "\e6d9"; } |
||||
|
|
||||
|
.icon-car:before { content: "\e6dc"; } |
||||
|
|
||||
|
.icon-addusergroup:before { content: "\e6dd"; } |
||||
|
|
||||
|
.icon-carryout:before { content: "\e6df"; } |
||||
|
|
||||
|
.icon-deleteuser:before { content: "\e6e0"; } |
||||
|
|
||||
|
.icon-deleteusergroup:before { content: "\e6e1"; } |
||||
|
|
||||
|
.icon-man:before { content: "\e6e2"; } |
||||
|
|
||||
|
.icon-isv:before { content: "\e6e3"; } |
||||
|
|
||||
|
.icon-gift:before { content: "\e6e4"; } |
||||
|
|
||||
|
.icon-idcard:before { content: "\e6e5"; } |
||||
|
|
||||
|
.icon-medicinebox:before { content: "\e6e6"; } |
||||
|
|
||||
|
.icon-redenvelopes:before { content: "\e6e7"; } |
||||
|
|
||||
|
.icon-rest:before { content: "\e6e8"; } |
||||
|
|
||||
|
.icon-Safety:before { content: "\e6ea"; } |
||||
|
|
||||
|
.icon-wallet:before { content: "\e6eb"; } |
||||
|
|
||||
|
.icon-woman:before { content: "\e6ec"; } |
||||
|
|
||||
|
.icon-adduser:before { content: "\e6ed"; } |
||||
|
|
||||
|
.icon-bank:before { content: "\e6ee"; } |
||||
|
|
||||
|
.icon-Trophy:before { content: "\e6ef"; } |
||||
|
|
||||
|
.icon-loading1:before { content: "\e6ae"; } |
||||
|
|
||||
|
.icon-loading2:before { content: "\e64d"; } |
||||
|
|
||||
|
.icon-like2:before { content: "\e69d"; } |
||||
|
|
||||
|
.icon-dislike2:before { content: "\e69e"; } |
||||
|
|
||||
|
.icon-like1:before { content: "\e64c"; } |
||||
|
|
||||
|
.icon-dislike1:before { content: "\e64b"; } |
||||
|
|
||||
|
.icon-bulb1:before { content: "\e649"; } |
||||
|
|
||||
|
.icon-rocket1:before { content: "\e90f"; } |
||||
|
|
||||
|
.icon-select1:before { content: "\e64a"; } |
||||
|
|
||||
|
.icon-apple1:before { content: "\e68c"; } |
||||
|
|
||||
|
.icon-apple-o:before { content: "\e6d4"; } |
||||
|
|
||||
|
.icon-android1:before { content: "\e938"; } |
||||
|
|
||||
|
.icon-android:before { content: "\e68d"; } |
||||
|
|
||||
|
.icon-aliwangwang-o1:before { content: "\e68f"; } |
||||
|
|
||||
|
.icon-aliwangwang:before { content: "\e68e"; } |
||||
|
|
||||
|
.icon-pay-circle1:before { content: "\e6a5"; } |
||||
|
|
||||
|
.icon-pay-circle-o1:before { content: "\e6a6"; } |
||||
|
|
||||
|
.icon-poweroff:before { content: "\e6d5"; } |
||||
|
|
||||
|
.icon-trademark:before { content: "\e651"; } |
||||
|
|
||||
|
.icon-find:before { content: "\e6db"; } |
||||
|
|
||||
|
.icon-copyright:before { content: "\e6de"; } |
||||
|
|
||||
|
.icon-sound:before { content: "\e6e9"; } |
||||
|
|
||||
|
.icon-earth:before { content: "\e6f1"; } |
||||
|
|
||||
|
.icon-wifi:before { content: "\e6d6"; } |
||||
|
|
||||
|
.icon-sync:before { content: "\e6da"; } |
||||
|
|
||||
|
.icon-login:before { content: "\e657"; } |
||||
|
|
||||
|
.icon-logout:before { content: "\e65a"; } |
||||
|
|
||||
|
.icon-reload1:before { content: "\e616"; } |
||||
|
|
||||
|
.icon-message1:before { content: "\e6ab"; } |
||||
|
|
||||
|
.icon-shake:before { content: "\e94f"; } |
||||
|
|
||||
|
.icon-API:before { content: "\e951"; } |
||||
|
|
||||
|
.icon-appstore-o:before { content: "\e695"; } |
||||
|
|
||||
|
.icon-appstore1:before { content: "\e696"; } |
||||
|
|
||||
|
.icon-scan1:before { content: "\e697"; } |
||||
|
|
||||
|
.icon-exception1:before { content: "\e665"; } |
||||
|
|
||||
|
.icon-contacts:before { content: "\e6f0"; } |
||||
|
|
||||
|
.icon-solution1:before { content: "\e66f"; } |
||||
|
|
||||
|
.icon-fork:before { content: "\e6f2"; } |
||||
|
|
||||
|
.icon-edit1:before { content: "\e692"; } |
||||
|
|
After Width: | Height: | Size: 140 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 21 KiB |
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 21 KiB |
After Width: | Height: | Size: 21 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 21 KiB |
After Width: | Height: | Size: 202 KiB |
After Width: | Height: | Size: 725 B |
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 169 KiB |
After Width: | Height: | Size: 8.7 KiB |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 524 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 873 B |
After Width: | Height: | Size: 206 KiB |
After Width: | Height: | Size: 150 B |
After Width: | Height: | Size: 950 B |
After Width: | Height: | Size: 873 B |