release: 第一版工程提交
This commit is contained in:
commit
8fd3a287a8
103
.cz-config.js
Normal file
103
.cz-config.js
Normal file
@ -0,0 +1,103 @@
|
||||
module.exports = {
|
||||
// type 类型(定义之后,可通过上下键选择)
|
||||
types: [
|
||||
{ value: 'improvement', name: 'improvement: 功能优化' },
|
||||
{ value: 'fix', name: 'fix: 修复 bug' },
|
||||
{ value: 'feat', name: 'feat: 新增功能' },
|
||||
{ value: 'style', name: 'style: 代码格式(不影响功能,例如空格、分号等格式修正)' },
|
||||
{ value: 'docs', name: 'docs: 文档变更' },
|
||||
{ value: 'refactor', name: 'refactor: 代码重构(不包括 bug 修复、功能新增)' },
|
||||
{ value: 'perf', name: 'perf: 性能优化' },
|
||||
{ value: 'test', name: 'test: 添加、修改测试用例' },
|
||||
{
|
||||
value: 'ci',
|
||||
name: 'ci: 修改 CI 配置、脚本(如打包部署脚本、dockerfile等)'
|
||||
},
|
||||
{ value: 'revert', name: 'revert: 回滚 commit' },
|
||||
{
|
||||
value: 'build',
|
||||
name: 'build: 构建流程、外部依赖变更(如升级 npm 包、修改 webpack 配置等)'
|
||||
},
|
||||
{
|
||||
value: 'chore',
|
||||
name: 'chore: 版本发布或对构建过程或辅助工具和库的更改(不影响源文件、测试用例)'
|
||||
}
|
||||
// { value: ':bug: fix', name: '🐛 fix: 修复 bug' },
|
||||
// { value: ':sparkles: feat', name: '✨ feat: 新增功能' },
|
||||
// {
|
||||
// value: ':lipstick: style',
|
||||
// name: '💄 style: 代码格式(不影响功能,例如空格、分号等格式修正)'
|
||||
// },
|
||||
// { value: ':memo: docs', name: '📝 docs: 文档变更' },
|
||||
// { value: ':recycle: refactor', name: '♻️ refactor: 代码重构(不包括 bug 修复、功能新增)' },
|
||||
// { value: ':zap: perf', name: '⚡️ perf: 性能优化' },
|
||||
// { value: ':white_check_mark: test', name: '✅ test: 添加、修改测试用例' },
|
||||
// {
|
||||
// value: ':hammer: chore',
|
||||
// name: '🔨 chore: 对构建过程或辅助工具和库的更改(不影响源文件、测试用例)'
|
||||
// },
|
||||
// { value: ':wrench: ci', name: '🔧 ci: 修改 CI 配置、脚本' },
|
||||
// { value: ':rocket: deps', name: '🚀 deps: 升级依赖' }
|
||||
// {
|
||||
// value: ':bookmark: release',
|
||||
// name: '🔖 release: 版本发布'
|
||||
// }
|
||||
],
|
||||
|
||||
// scope 类型(定义之后,可通过上下键选择)
|
||||
scopes: [
|
||||
['custom', '自定义范围,例如sys/user'],
|
||||
['utils', 'utils 相关'],
|
||||
['router', 'router 相关']
|
||||
].map(([value, description]) => {
|
||||
return {
|
||||
value,
|
||||
name: `${value.padEnd(30)} (${description})`
|
||||
}
|
||||
}),
|
||||
// 是否允许自定义填写 scope,在 scope 选择的时候,会有 empty 和 custom 可以选择。
|
||||
// allowCustomScopes: true,
|
||||
// allowTicketNumber: false,
|
||||
// isTicketNumberRequired: false,
|
||||
// ticketNumberPrefix: 'TICKET-',
|
||||
// ticketNumberRegExp: '\\d{1,5}',
|
||||
|
||||
// 针对每一个 type 去定义对应的 scopes,例如 fix
|
||||
scopeOverrides: {
|
||||
chore: [
|
||||
{ value: 'release', name: 'release 版本发布' },
|
||||
{ value: 'custom', name: 'custom 自定义scope' }
|
||||
],
|
||||
ci: [
|
||||
{ value: 'deploy', name: 'deploy 部署脚本' },
|
||||
{ value: 'docker', name: 'docker docker相关' },
|
||||
{ value: 'custom', name: 'custom 自定义scope' }
|
||||
],
|
||||
build: [
|
||||
{ value: 'deps', name: 'deps 依赖变更' },
|
||||
{ value: 'custom', name: 'custom 自定义scope' }
|
||||
]
|
||||
},
|
||||
// 交互提示信息
|
||||
messages: {
|
||||
type: '确保本次提交遵循 Angular 规范!\n选择你要提交的类型:',
|
||||
scope: '\n选择一个 scope(可选):',
|
||||
customScope: '请输入自定义的 scope:',
|
||||
subject: '填写简短精炼的变更描述:\n',
|
||||
body: '填写更加详细的变更描述(可选)。使用 "|" 换行:\n',
|
||||
breaking: '列举非兼容性重大的变更(可选):\n',
|
||||
footer: '列举出所有变更的 ISSUES CLOSED(可选)。 例如: #31, #34:\n',
|
||||
confirmCommit: '确认提交?'
|
||||
},
|
||||
|
||||
// ['feat', 'fix']设置只有 type 选择了 feat 或 fix,才询问 breaking message
|
||||
allowBreakingChanges: [],
|
||||
// 跳过要询问的步骤
|
||||
skipQuestions: ['body'],
|
||||
|
||||
// subject 限制长度
|
||||
subjectLimit: 100,
|
||||
breaklineChar: '|' // 支持 body 和 footer
|
||||
// footerPrefix : 'ISSUES CLOSED:'
|
||||
// askForBreakingChangeFirst : true,
|
||||
}
|
16
.editorconfig
Normal file
16
.editorconfig
Normal file
@ -0,0 +1,16 @@
|
||||
# Editor configuration, see http://editorconfig.org
|
||||
|
||||
# 表示是最顶层的 EditorConfig 配置文件
|
||||
root = true
|
||||
|
||||
[*] # 表示所有文件适用
|
||||
charset = utf-8 # 设置文件字符集为 utf-8
|
||||
indent_style = space # 缩进风格(tab | space)
|
||||
indent_size = 2 # 缩进大小
|
||||
end_of_line = lf # 控制换行类型(lf | cr | crlf)
|
||||
trim_trailing_whitespace = true # 去除行首的任意空白字符
|
||||
insert_final_newline = true # 始终在文件末尾插入一个新行
|
||||
|
||||
[*.md] # 表示仅 md 文件适用以下规则
|
||||
max_line_length = off
|
||||
trim_trailing_whitespace = false
|
281
.eslintrc-auto-import.json
Normal file
281
.eslintrc-auto-import.json
Normal file
@ -0,0 +1,281 @@
|
||||
{
|
||||
"globals": {
|
||||
"Component": true,
|
||||
"ComponentPublicInstance": true,
|
||||
"ComputedRef": true,
|
||||
"EffectScope": true,
|
||||
"ExtractDefaultPropTypes": true,
|
||||
"ExtractPropTypes": true,
|
||||
"ExtractPublicPropTypes": true,
|
||||
"InjectionKey": true,
|
||||
"PropType": true,
|
||||
"Ref": true,
|
||||
"VNode": true,
|
||||
"WritableComputedRef": true,
|
||||
"asyncComputed": true,
|
||||
"autoResetRef": true,
|
||||
"computed": true,
|
||||
"computedAsync": true,
|
||||
"computedEager": true,
|
||||
"computedInject": true,
|
||||
"computedWithControl": true,
|
||||
"controlledComputed": true,
|
||||
"controlledRef": true,
|
||||
"createApp": true,
|
||||
"createEventHook": true,
|
||||
"createGlobalState": true,
|
||||
"createInjectionState": true,
|
||||
"createReactiveFn": true,
|
||||
"createSharedComposable": true,
|
||||
"createUnrefFn": true,
|
||||
"customRef": true,
|
||||
"debouncedRef": true,
|
||||
"debouncedWatch": true,
|
||||
"defineAsyncComponent": true,
|
||||
"defineComponent": true,
|
||||
"eagerComputed": true,
|
||||
"effectScope": true,
|
||||
"extendRef": true,
|
||||
"getCurrentInstance": true,
|
||||
"getCurrentScope": true,
|
||||
"h": true,
|
||||
"ignorableWatch": true,
|
||||
"inject": true,
|
||||
"isDefined": true,
|
||||
"isProxy": true,
|
||||
"isReactive": true,
|
||||
"isReadonly": true,
|
||||
"isRef": true,
|
||||
"makeDestructurable": true,
|
||||
"markRaw": true,
|
||||
"nextTick": true,
|
||||
"onActivated": true,
|
||||
"onBeforeMount": true,
|
||||
"onBeforeRouteLeave": true,
|
||||
"onBeforeRouteUpdate": true,
|
||||
"onBeforeUnmount": true,
|
||||
"onBeforeUpdate": true,
|
||||
"onClickOutside": true,
|
||||
"onDeactivated": true,
|
||||
"onErrorCaptured": true,
|
||||
"onKeyStroke": true,
|
||||
"onLongPress": true,
|
||||
"onMounted": true,
|
||||
"onRenderTracked": true,
|
||||
"onRenderTriggered": true,
|
||||
"onScopeDispose": true,
|
||||
"onServerPrefetch": true,
|
||||
"onStartTyping": true,
|
||||
"onUnmounted": true,
|
||||
"onUpdated": true,
|
||||
"pausableWatch": true,
|
||||
"provide": true,
|
||||
"reactify": true,
|
||||
"reactifyObject": true,
|
||||
"reactive": true,
|
||||
"reactiveComputed": true,
|
||||
"reactiveOmit": true,
|
||||
"reactivePick": true,
|
||||
"readonly": true,
|
||||
"ref": true,
|
||||
"refAutoReset": true,
|
||||
"refDebounced": true,
|
||||
"refDefault": true,
|
||||
"refThrottled": true,
|
||||
"refWithControl": true,
|
||||
"resolveComponent": true,
|
||||
"resolveRef": true,
|
||||
"resolveUnref": true,
|
||||
"shallowReactive": true,
|
||||
"shallowReadonly": true,
|
||||
"shallowRef": true,
|
||||
"syncRef": true,
|
||||
"syncRefs": true,
|
||||
"templateRef": true,
|
||||
"throttledRef": true,
|
||||
"throttledWatch": true,
|
||||
"toRaw": true,
|
||||
"toReactive": true,
|
||||
"toRef": true,
|
||||
"toRefs": true,
|
||||
"toValue": true,
|
||||
"triggerRef": true,
|
||||
"tryOnBeforeMount": true,
|
||||
"tryOnBeforeUnmount": true,
|
||||
"tryOnMounted": true,
|
||||
"tryOnScopeDispose": true,
|
||||
"tryOnUnmounted": true,
|
||||
"unref": true,
|
||||
"unrefElement": true,
|
||||
"until": true,
|
||||
"useActiveElement": true,
|
||||
"useArrayEvery": true,
|
||||
"useArrayFilter": true,
|
||||
"useArrayFind": true,
|
||||
"useArrayFindIndex": true,
|
||||
"useArrayFindLast": true,
|
||||
"useArrayJoin": true,
|
||||
"useArrayMap": true,
|
||||
"useArrayReduce": true,
|
||||
"useArraySome": true,
|
||||
"useArrayUnique": true,
|
||||
"useAsyncQueue": true,
|
||||
"useAsyncState": true,
|
||||
"useAttrs": true,
|
||||
"useBase64": true,
|
||||
"useBattery": true,
|
||||
"useBluetooth": true,
|
||||
"useBreakpoints": true,
|
||||
"useBroadcastChannel": true,
|
||||
"useBrowserLocation": true,
|
||||
"useCached": true,
|
||||
"useClipboard": true,
|
||||
"useCloned": true,
|
||||
"useColorMode": true,
|
||||
"useConfirmDialog": true,
|
||||
"useCounter": true,
|
||||
"useCssModule": true,
|
||||
"useCssVar": true,
|
||||
"useCssVars": true,
|
||||
"useCurrentElement": true,
|
||||
"useCycleList": true,
|
||||
"useDark": true,
|
||||
"useDateFormat": true,
|
||||
"useDebounce": true,
|
||||
"useDebounceFn": true,
|
||||
"useDebouncedRefHistory": true,
|
||||
"useDeviceMotion": true,
|
||||
"useDeviceOrientation": true,
|
||||
"useDevicePixelRatio": true,
|
||||
"useDevicesList": true,
|
||||
"useDisplayMedia": true,
|
||||
"useDocumentVisibility": true,
|
||||
"useDraggable": true,
|
||||
"useDropZone": true,
|
||||
"useElementBounding": true,
|
||||
"useElementByPoint": true,
|
||||
"useElementHover": true,
|
||||
"useElementSize": true,
|
||||
"useElementVisibility": true,
|
||||
"useEventBus": true,
|
||||
"useEventListener": true,
|
||||
"useEventSource": true,
|
||||
"useEyeDropper": true,
|
||||
"useFavicon": true,
|
||||
"useFetch": true,
|
||||
"useFileDialog": true,
|
||||
"useFileSystemAccess": true,
|
||||
"useFocus": true,
|
||||
"useFocusWithin": true,
|
||||
"useFps": true,
|
||||
"useFullscreen": true,
|
||||
"useGamepad": true,
|
||||
"useGeolocation": true,
|
||||
"useIdle": true,
|
||||
"useImage": true,
|
||||
"useInfiniteScroll": true,
|
||||
"useIntersectionObserver": true,
|
||||
"useInterval": true,
|
||||
"useIntervalFn": true,
|
||||
"useKeyModifier": true,
|
||||
"useLastChanged": true,
|
||||
"useLink": true,
|
||||
"useLocalStorage": true,
|
||||
"useMagicKeys": true,
|
||||
"useManualRefHistory": true,
|
||||
"useMediaControls": true,
|
||||
"useMediaQuery": true,
|
||||
"useMemoize": true,
|
||||
"useMemory": true,
|
||||
"useMounted": true,
|
||||
"useMouse": true,
|
||||
"useMouseInElement": true,
|
||||
"useMousePressed": true,
|
||||
"useMutationObserver": true,
|
||||
"useNavigatorLanguage": true,
|
||||
"useNetwork": true,
|
||||
"useNow": true,
|
||||
"useObjectUrl": true,
|
||||
"useOffsetPagination": true,
|
||||
"useOnline": true,
|
||||
"usePageLeave": true,
|
||||
"useParallax": true,
|
||||
"usePermission": true,
|
||||
"usePointer": true,
|
||||
"usePointerLock": true,
|
||||
"usePointerSwipe": true,
|
||||
"usePreferredColorScheme": true,
|
||||
"usePreferredContrast": true,
|
||||
"usePreferredDark": true,
|
||||
"usePreferredLanguages": true,
|
||||
"usePreferredReducedMotion": true,
|
||||
"usePrevious": true,
|
||||
"useRafFn": true,
|
||||
"useRefHistory": true,
|
||||
"useResizeObserver": true,
|
||||
"useRoute": true,
|
||||
"useRouter": true,
|
||||
"useScreenOrientation": true,
|
||||
"useScreenSafeArea": true,
|
||||
"useScriptTag": true,
|
||||
"useScroll": true,
|
||||
"useScrollLock": true,
|
||||
"useSessionStorage": true,
|
||||
"useShare": true,
|
||||
"useSlots": true,
|
||||
"useSorted": true,
|
||||
"useSpeechRecognition": true,
|
||||
"useSpeechSynthesis": true,
|
||||
"useStepper": true,
|
||||
"useStorage": true,
|
||||
"useStorageAsync": true,
|
||||
"useStyleTag": true,
|
||||
"useSupported": true,
|
||||
"useSwipe": true,
|
||||
"useTemplateRefsList": true,
|
||||
"useTextDirection": true,
|
||||
"useTextSelection": true,
|
||||
"useTextareaAutosize": true,
|
||||
"useThrottle": true,
|
||||
"useThrottleFn": true,
|
||||
"useThrottledRefHistory": true,
|
||||
"useTimeAgo": true,
|
||||
"useTimeout": true,
|
||||
"useTimeoutFn": true,
|
||||
"useTimeoutPoll": true,
|
||||
"useTimestamp": true,
|
||||
"useTitle": true,
|
||||
"useToNumber": true,
|
||||
"useToString": true,
|
||||
"useToggle": true,
|
||||
"useTransition": true,
|
||||
"useUrlSearchParams": true,
|
||||
"useUserMedia": true,
|
||||
"useVModel": true,
|
||||
"useVModels": true,
|
||||
"useVibrate": true,
|
||||
"useVirtualList": true,
|
||||
"useWakeLock": true,
|
||||
"useWebNotification": true,
|
||||
"useWebSocket": true,
|
||||
"useWebWorker": true,
|
||||
"useWebWorkerFn": true,
|
||||
"useWindowFocus": true,
|
||||
"useWindowScroll": true,
|
||||
"useWindowSize": true,
|
||||
"watch": true,
|
||||
"watchArray": true,
|
||||
"watchAtMost": true,
|
||||
"watchDebounced": true,
|
||||
"watchEffect": true,
|
||||
"watchIgnorable": true,
|
||||
"watchOnce": true,
|
||||
"watchPausable": true,
|
||||
"watchPostEffect": true,
|
||||
"watchSyncEffect": true,
|
||||
"watchThrottled": true,
|
||||
"watchTriggerable": true,
|
||||
"watchWithFilter": true,
|
||||
"whenever": true
|
||||
}
|
||||
}
|
56
.eslintrc.js
Normal file
56
.eslintrc.js
Normal file
@ -0,0 +1,56 @@
|
||||
module.exports = {
|
||||
env: {
|
||||
browser: true,
|
||||
es2021: true,
|
||||
node: true
|
||||
},
|
||||
extends: [
|
||||
'plugin:vue/vue3-essential',
|
||||
'airbnb-base',
|
||||
'plugin:prettier/recommended', // 添加 prettier 插件
|
||||
'./.eslintrc-auto-import.json'
|
||||
],
|
||||
parserOptions: {
|
||||
ecmaVersion: 12,
|
||||
parser: '@typescript-eslint/parser',
|
||||
sourceType: 'module'
|
||||
},
|
||||
globals: {
|
||||
defineProps: true,
|
||||
defineEmits: true,
|
||||
defineExpose: true
|
||||
},
|
||||
settings: {},
|
||||
plugins: ['vue', '@typescript-eslint'],
|
||||
rules: {
|
||||
'import/no-unresolved': 'off',
|
||||
'import/extensions': 'off',
|
||||
// 开放入参修改值
|
||||
'no-param-reassign': [
|
||||
'error',
|
||||
{
|
||||
props: true,
|
||||
ignorePropertyModificationsFor: [
|
||||
'e', // for e.returnvalue
|
||||
'ctx', // for Koa routing
|
||||
'req', // for Express requests
|
||||
'request', // for Express requests
|
||||
'res', // for Express responses
|
||||
'response', // for Express responses
|
||||
'state' // for vuex state
|
||||
]
|
||||
}
|
||||
],
|
||||
'import/prefer-default-export': 'off',
|
||||
'no-unused-vars': 'off',
|
||||
'@typescript-eslint/no-unused-vars': [
|
||||
'error',
|
||||
{
|
||||
vars: 'all',
|
||||
args: 'after-used',
|
||||
ignoreRestSiblings: true
|
||||
}
|
||||
],
|
||||
'import/no-extraneous-dependencies': ['error', { devDependencies: true }]
|
||||
}
|
||||
}
|
33
.gitattributes
vendored
Normal file
33
.gitattributes
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
* text=auto
|
||||
|
||||
# Force the following filetypes to have unix eols, so Windows does not break them
|
||||
*.* text eol=lf
|
||||
|
||||
# Separate configuration for files without suffix
|
||||
LICENSE text eol=lf
|
||||
Dockerfile text eol=lf
|
||||
pre-commit text eol=lf
|
||||
commit-msg text eol=lf
|
||||
|
||||
# These files are binary and should be left untouched
|
||||
# (binary is a macro for -text -diff)
|
||||
*.ico binary
|
||||
*.jpg binary
|
||||
*.jpeg binary
|
||||
*.png binary
|
||||
|
||||
*.pdf binary
|
||||
*.doc binary
|
||||
*.docx binary
|
||||
*.ppt binary
|
||||
*.pptx binary
|
||||
*.xls binary
|
||||
*.xlsx binary
|
||||
*.exe binary
|
||||
|
||||
*.ttf binary
|
||||
*.woff binary
|
||||
*.woff2 binary
|
||||
*.eot binary
|
||||
*.otf binary
|
||||
# Add more binary...
|
56
.gitea/workflows/build.yaml
Normal file
56
.gitea/workflows/build.yaml
Normal file
@ -0,0 +1,56 @@
|
||||
name: Build
|
||||
|
||||
# 打标签时触发构建,另外标签需v开头,例如v1.0.0,需要配置DOCKER_PASSWORD的secrets
|
||||
# 构建后镜像为 ${docker_registry}/${docker_username}/${repo_name}:1.0.0
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- v*
|
||||
|
||||
env:
|
||||
DOCKER_REGISTRY: registry.cn-hangzhou.aliyuncs.com
|
||||
DOCKER_USERNAME: rsjst
|
||||
|
||||
jobs:
|
||||
build-image:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Setup Pnpm and Install
|
||||
uses: seepine/action-setup-pnpm@v1
|
||||
|
||||
- name: Project Build
|
||||
run: pnpm run build
|
||||
|
||||
- name: Get Meta
|
||||
id: meta
|
||||
run: |
|
||||
echo REPO_NAME=$(echo ${GITHUB_REPOSITORY} | awk -F"/" '{print $2}') >> $GITHUB_OUTPUT
|
||||
echo REPO_VERSION=$(echo ${{ github.ref }} | awk -F"/" '{print $3}' | awk -F"v" '{print $2}') >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Docker build push
|
||||
uses: seepine/action-docker-build-push@v1
|
||||
with:
|
||||
registry: ${{ env.DOCKER_REGISTRY }}
|
||||
username: ${{ env.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
context: .
|
||||
file: ./docker/Dockerfile
|
||||
platforms: linux/amd64,linux/arm64
|
||||
tags: |
|
||||
${{ env.DOCKER_REGISTRY }}/${{ env.DOCKER_USERNAME }}/${{ steps.meta.outputs.REPO_NAME }}:latest
|
||||
${{ env.DOCKER_REGISTRY }}/${{ env.DOCKER_USERNAME }}/${{ steps.meta.outputs.REPO_NAME }}:${{ steps.meta.outputs.REPO_VERSION }}
|
||||
|
||||
- name: WeChat Work notification
|
||||
uses: seepine/action-wechat-work@master
|
||||
env:
|
||||
WECHAT_WORK_BOT_WEBHOOK: ${{ secrets.WECHAT_WORK_BOT_WEBHOOK }}
|
||||
if: ${{ env.WECHAT_WORK_BOT_WEBHOOK != '' }}
|
||||
with:
|
||||
msgtype: markdown
|
||||
content: "${{ steps.meta.outputs.REPO_NAME }} build docker image success.\n
|
||||
> Tag: ${{ env.DOCKER_REGISTRY }}/${{ env.DOCKER_USERNAME }}/${{ steps.meta.outputs.REPO_NAME }}:${{ steps.meta.outputs.REPO_VERSION }}"
|
76
.gitea/workflows/check.yml
Normal file
76
.gitea/workflows/check.yml
Normal file
@ -0,0 +1,76 @@
|
||||
name: Checks
|
||||
|
||||
on:
|
||||
- pull_request
|
||||
|
||||
jobs:
|
||||
setup:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Setup Pnpm and Install
|
||||
uses: seepine/action-setup-pnpm@v1
|
||||
|
||||
eslint:
|
||||
needs: setup
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Setup Pnpm and Install
|
||||
uses: seepine/action-setup-pnpm@v1
|
||||
|
||||
- name: Eslint Test
|
||||
run: npx eslint --ext ".vue,.js,.jsx,.ts,.tsx" src/ --max-warnings=0
|
||||
|
||||
tslint:
|
||||
needs: setup
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Setup Pnpm and Install
|
||||
uses: seepine/action-setup-pnpm@v1
|
||||
|
||||
- name: Tslint Test
|
||||
run: pnpm type-check
|
||||
|
||||
commit-lint:
|
||||
needs: setup
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 10
|
||||
|
||||
- name: Setup Pnpm and Install
|
||||
uses: seepine/action-setup-pnpm@v1
|
||||
|
||||
- name: Commit lint
|
||||
run: npx commitlint --to HEAD --verbose
|
||||
|
||||
build:
|
||||
needs: setup
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Setup Pnpm and Install
|
||||
uses: seepine/action-setup-pnpm@v1
|
||||
|
||||
- name: Build
|
||||
run: pnpm build
|
29
.gitignore
vendored
Normal file
29
.gitignore
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
node_modules
|
||||
.DS_Store
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
||||
# Log files
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
auto-imports.d.ts
|
||||
components.d.ts
|
||||
|
||||
yarn.lock
|
||||
package-lock.lock
|
8
.hintrc
Normal file
8
.hintrc
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": [
|
||||
"development"
|
||||
],
|
||||
"hints": {
|
||||
"meta-viewport": "off"
|
||||
}
|
||||
}
|
4
.husky/commit-msg
Normal file
4
.husky/commit-msg
Normal file
@ -0,0 +1,4 @@
|
||||
#!/usr/bin/env sh
|
||||
. "$(dirname -- "$0")/_/husky.sh"
|
||||
|
||||
npx --no-install commitlint --edit
|
4
.husky/pre-commit
Normal file
4
.husky/pre-commit
Normal file
@ -0,0 +1,4 @@
|
||||
#!/usr/bin/env sh
|
||||
. "$(dirname -- "$0")/_/husky.sh"
|
||||
|
||||
npx lint-staged
|
11
.prettierrc
Normal file
11
.prettierrc
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"useTabs": false,
|
||||
"tabWidth": 2,
|
||||
"printWidth": 100,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "none",
|
||||
"bracketSpacing": true,
|
||||
"semi": false,
|
||||
"plugins": ["prettier-plugin-tailwindcss"],
|
||||
"tailwindConfig": "./tailwind.config.js"
|
||||
}
|
22
.vscode/extensions.json
vendored
Normal file
22
.vscode/extensions.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"recommendations": [
|
||||
// volar
|
||||
"Vue.volar",
|
||||
// editor
|
||||
"EditorConfig.EditorConfig",
|
||||
// prettier
|
||||
"esbenp.prettier-vscode",
|
||||
// eslint
|
||||
"dbaeumer.vscode-eslint",
|
||||
// package 包跳转
|
||||
"ravenq.vscode-goto-node-modules",
|
||||
// html 标签自动重命名
|
||||
"formulahendry.auto-rename-tag",
|
||||
// git 插件
|
||||
"mhutchie.git-graph",
|
||||
// tailwindcss 插件
|
||||
"bradlc.vscode-tailwindcss",
|
||||
// 彩虹插件
|
||||
"oderwat.indent-rainbow"
|
||||
]
|
||||
}
|
44
.vscode/settings.json
vendored
Normal file
44
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
{
|
||||
// 保存时执行eslint
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": "explicit"
|
||||
},
|
||||
// 从不展示扩展缩写
|
||||
"emmet.showExpandedAbbreviation": "never",
|
||||
// 关闭代码区域小地图
|
||||
"editor.minimap.enabled": false,
|
||||
// 代码过长换行
|
||||
"editor.wordWrap": "on",
|
||||
// 开启文件折叠
|
||||
"explorer.fileNesting.enabled": true,
|
||||
"explorer.fileNesting.expand": false,
|
||||
"explorer.fileNesting.patterns": {
|
||||
// 把大部分配置文件都折叠到package.json里
|
||||
"package.json": ".*, index.html, yarn.lock, *.js, *.ts, *.json, *.sh"
|
||||
},
|
||||
// 隐藏某些文件或目录
|
||||
"files.exclude": {
|
||||
"**/.git": true,
|
||||
"**/.svn": true,
|
||||
"**/.hg": true,
|
||||
"**/CVS": true,
|
||||
"**/.DS_Store": true,
|
||||
"**/Thumbs.db": true,
|
||||
".husky": true
|
||||
},
|
||||
// 自定义彩虹插件颜色
|
||||
"indentRainbow.colors": [
|
||||
"rgba(245, 63, 63, 0.07)",
|
||||
"rgba(255, 125, 0, 0.07)",
|
||||
"rgba(247, 186, 30, 0.07)",
|
||||
"rgba(250, 220, 25, 0.07)",
|
||||
"rgba(159, 219, 29, 0.07)",
|
||||
"rgba(0, 180, 42, 0.07)",
|
||||
"rgba(20, 201, 201, 0.07)",
|
||||
"rgba(52, 145, 250, 0.07)",
|
||||
"rgba(22, 93, 255, 0.07)",
|
||||
"rgba(114, 46, 209, 0.07)",
|
||||
"rgba(217, 26, 217, 0.07)",
|
||||
"rgba(245, 49, 157, 0.07)"
|
||||
]
|
||||
}
|
172
README.md
Normal file
172
README.md
Normal file
@ -0,0 +1,172 @@
|
||||
# FxBootUi
|
||||
|
||||
## 一、开发准备
|
||||
|
||||
### 1.开发工具:VsCode
|
||||
|
||||
### 2.安装插件
|
||||
|
||||
打开项目后右下角会有建议安装,选择安装即可,也可自己一个个搜索安装
|
||||
|
||||
- Vue.volar
|
||||
- EditorConfig.EditorConfig
|
||||
- esbenp.prettier-vscode
|
||||
- dbaeumer.vscode-eslint
|
||||
- ravenq.vscode-goto-node-modules
|
||||
- formulahendry.auto-rename-tag
|
||||
- mhutchie.git-graph
|
||||
|
||||
## 二、快速入门
|
||||
|
||||
### 1.修改项目信息
|
||||
|
||||
配置根目录的`package.json`,修改项目名和版本号
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "fxboot-ui",
|
||||
"version": "0.1.0"
|
||||
}
|
||||
```
|
||||
|
||||
### 2.安装依赖
|
||||
|
||||
```shell
|
||||
# 若未安装pnpm请先执行npm i -g pnpm
|
||||
pnpm i
|
||||
```
|
||||
|
||||
### 3.运行
|
||||
|
||||
```shell
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
## 三、代码管理
|
||||
|
||||
### 1.配置用户名和邮箱
|
||||
|
||||
将以下命令中 `yourName` 和 `your@email.com` 替换为你的用户名和邮箱并执行
|
||||
|
||||
```shell
|
||||
git config user.name yourName
|
||||
git config user.email your@email.com
|
||||
```
|
||||
|
||||
### 2.非 windows 系统可能需要先执行命令
|
||||
|
||||
```shell
|
||||
chmod 755 .husky/pre-commit
|
||||
chmod 755 .husky/commit-msg
|
||||
```
|
||||
|
||||
### 3.保存变更文件
|
||||
|
||||
使用 `git add xxx` 或 VsCode 左侧的源代码管理面板提交变更文件
|
||||
|
||||
### 4.提交代码
|
||||
|
||||
执行命令后,按提示输入内容即可
|
||||
|
||||
```shell
|
||||
pnpm cz
|
||||
```
|
||||
|
||||
### 5.推送到仓库
|
||||
|
||||
```shell
|
||||
git push
|
||||
```
|
||||
|
||||
### 6.查看提交记录
|
||||
|
||||
通过`菜单栏->查看->命令面板`(或快捷键打开也可),输入`git log`,选择建议项`Git Graph: View Git Graph (git log)`即可
|
||||
|
||||
## 四、部署
|
||||
|
||||
### 1.配置镜像
|
||||
|
||||
配置根目录的 `deploy.sh` 文件,修改 `HUB` 为你的镜像地址
|
||||
|
||||
```shell
|
||||
HUB=registry.cn-hangzhou.aliyuncs.com/rsjst
|
||||
```
|
||||
|
||||
### 2.打包
|
||||
|
||||
```shell
|
||||
sh deploy.sh
|
||||
```
|
||||
|
||||
### 3.部署
|
||||
|
||||
配置 dockerSwarm 的 stack 中的 image 为打包的镜像即可,例如
|
||||
|
||||
```yml
|
||||
version: '3.7'
|
||||
services:
|
||||
fx-boot-ui:
|
||||
image: registry.cn-hangzhou.aliyuncs.com/rsjst/fx-boot-ui:0.1.0
|
||||
environment:
|
||||
# 配置为服务器的ip地址:后端端口
|
||||
PROXY_PASS: http://192.168.1.1:8020/
|
||||
ports:
|
||||
# 映射为4000端口
|
||||
- 4000:80
|
||||
# 下述配置实现热更新,不需要可去除
|
||||
deploy:
|
||||
mode: replicated
|
||||
replicas: 1
|
||||
update_config:
|
||||
delay: 5s
|
||||
order: start-first
|
||||
```
|
||||
|
||||
### 4.配置 nginx
|
||||
|
||||
配置服务器上的nginx,代理转发到前端端口
|
||||
|
||||
```nginx
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:4000/;
|
||||
proxy_set_header Host $host:$server_port;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
}
|
||||
```
|
||||
|
||||
## 五、技术要点
|
||||
|
||||
Vue 3 + Typescript + Vite
|
||||
|
||||
- 编程语言:TypeScript 4.x + JavaScript
|
||||
- 构建工具:Vite 3.x
|
||||
- 前端框架:Vue 3.x
|
||||
- 路由工具:Vue Router 4.x
|
||||
- 状态管理:Pinia
|
||||
- UI 组件库:Arco
|
||||
- UI 组件库:Crco
|
||||
- CSS 预编译:Sass
|
||||
- HTTP 工具:Axios
|
||||
- Git Hook 工具:husky + lint-staged
|
||||
- 代码规范:EditorConfig + Prettier + ESLint + Airbnb JavaScript Style Guide
|
||||
- 提交规范:Commitizen + Commitlint
|
||||
|
||||
|
||||
## 六、相关文档
|
||||
|
||||
### 1.Vue3.X
|
||||
[快速上手|Vue.js](https://cn.vuejs.org/guide/quick-start.html)
|
||||
|
||||
### 2.Pinia
|
||||
[Pinia](https://pinia.vuejs.org/)
|
||||
|
||||
[Pinia Demo](./src/store/README.md)
|
||||
|
||||
### 3.Arco
|
||||
[Arco 组件库](https://arco.design/vue/component/button)
|
||||
|
||||
### 4.Crco
|
||||
[Crco 组件库](https://crco.seepine.com)
|
||||
|
||||
或从 `/src/views` 中任意子目录中,皆可查看 `crco` 的应用案例,例如 `/src/views/recruit/resume`
|
26
commitlint.config.js
Normal file
26
commitlint.config.js
Normal file
@ -0,0 +1,26 @@
|
||||
module.exports = {
|
||||
extends: [
|
||||
'@commitlint/config-conventional'
|
||||
// 'gitmoji'
|
||||
],
|
||||
rules: {
|
||||
'type-enum': [
|
||||
2,
|
||||
'always',
|
||||
[
|
||||
'build',
|
||||
'chore',
|
||||
'ci',
|
||||
'docs',
|
||||
'feat',
|
||||
'fix',
|
||||
'perf',
|
||||
'refactor',
|
||||
'revert',
|
||||
'style',
|
||||
'test',
|
||||
'improvement'
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
18
deploy.sh
Normal file
18
deploy.sh
Normal file
@ -0,0 +1,18 @@
|
||||
run() {
|
||||
echo "[RUN] " $*
|
||||
$*
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "[ERROR] fail"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
run npm run pre
|
||||
run npm run build
|
||||
|
||||
HUB=registry.cn-hangzhou.aliyuncs.com/rsjst
|
||||
NAME=$(cat package.json | grep "name" | sed 's/:/\n/g' | sed '1d' | sed 's/}//g' | sed 's/ //g' | sed 's/,//g' | sed 's/"//g')
|
||||
VERSION=$(cat package.json | grep "version" | sed 's/:/\n/g' | sed '1d' | sed 's/}//g' | sed 's/ //g' | sed 's/,//g' | sed 's/"//g')
|
||||
|
||||
run docker buildx build -t $HUB/$NAME:$VERSION --platform=linux/amd64,linux/arm64 -f ./docker/Dockerfile . --push
|
||||
run echo build and push $HUB/$NAME:$VERSION success
|
16
docker/Dockerfile
Normal file
16
docker/Dockerfile
Normal file
@ -0,0 +1,16 @@
|
||||
FROM git.zgfxrc.cn/registry/nginx:1.25-alpine-slim
|
||||
|
||||
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories \
|
||||
&& apk add --no-cache tzdata \
|
||||
&& cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
|
||||
&& apk del tzdata \
|
||||
&& echo "*/30 * * * * ntpd -d -q -n -p ntp.aliyun.com" >> /etc/crontabs/root
|
||||
|
||||
ENV LISTEN_PORT=80\
|
||||
SERVER_NAME=localhost\
|
||||
PROXY_PASS=http://127.0.0.1
|
||||
|
||||
ADD ./docker/ui.conf /etc/nginx/templates/default.conf.template
|
||||
|
||||
COPY ./dist/ /html
|
||||
RUN chmod -R 755 /html
|
31
docker/ui.conf
Normal file
31
docker/ui.conf
Normal file
@ -0,0 +1,31 @@
|
||||
server {
|
||||
listen ${LISTEN_PORT};
|
||||
server_name ${SERVER_NAME};
|
||||
|
||||
gzip on;
|
||||
gzip_min_length 1k;
|
||||
gzip_buffers 4 16k;
|
||||
gzip_http_version 1.1;
|
||||
gzip_comp_level 2;
|
||||
gzip_types text/plain application/javascript application/x-javascript text/javascript text/css application/xml;
|
||||
gzip_vary on;
|
||||
gzip_proxied expired no-cache no-store private auth;
|
||||
gzip_disable "MSIE [1-6]\.";
|
||||
|
||||
client_max_body_size 4000m;
|
||||
client_header_buffer_size 32k;
|
||||
large_client_header_buffers 4 32k;
|
||||
|
||||
location /webapi/ {
|
||||
proxy_pass ${PROXY_PASS};
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto http;
|
||||
}
|
||||
|
||||
location / {
|
||||
root /html;
|
||||
index index.html;
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
}
|
277
index.html
Normal file
277
index.html
Normal file
@ -0,0 +1,277 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no"
|
||||
/>
|
||||
<title>FxBoot</title>
|
||||
<link rel="stylesheet" href="/public/font-awesome-4.7.0/css/font-awesome.min.css" />
|
||||
<link rel="stylesheet" href="/public/iconfont/iconfont.css">
|
||||
<!-- <script src="https://cdn.bootcss.com/vConsole/3.2.0/vconsole.min.js"></script> -->
|
||||
<script>
|
||||
// let vConsole = new VConsole()
|
||||
</script>
|
||||
<style>
|
||||
#loader-wrapper {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 999999;
|
||||
}
|
||||
|
||||
#loader {
|
||||
display: block;
|
||||
position: relative;
|
||||
left: 50%;
|
||||
top: 42%;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
margin: -25px 0 0 -25px;
|
||||
border-radius: 50%;
|
||||
border: 3px solid transparent;
|
||||
/* COLOR 1 */
|
||||
border-top-color: #165dff;
|
||||
-webkit-animation: spin 2s linear infinite;
|
||||
/* Chrome, Opera 15+, Safari 5+ */
|
||||
-ms-animation: spin 2s linear infinite;
|
||||
/* Chrome, Opera 15+, Safari 5+ */
|
||||
-moz-animation: spin 2s linear infinite;
|
||||
/* Chrome, Opera 15+, Safari 5+ */
|
||||
-o-animation: spin 2s linear infinite;
|
||||
/* Chrome, Opera 15+, Safari 5+ */
|
||||
animation: spin 2s linear infinite;
|
||||
/* Chrome, Firefox 16+, IE 10+, Opera */
|
||||
z-index: 1001;
|
||||
}
|
||||
|
||||
#loader:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
left: 5px;
|
||||
right: 5px;
|
||||
bottom: 5px;
|
||||
border-radius: 50%;
|
||||
border: 3px solid transparent;
|
||||
/* COLOR 2 */
|
||||
border-top-color: #165dff;
|
||||
-webkit-animation: spin 3s linear infinite;
|
||||
/* Chrome, Opera 15+, Safari 5+ */
|
||||
-moz-animation: spin 3s linear infinite;
|
||||
/* Chrome, Opera 15+, Safari 5+ */
|
||||
-o-animation: spin 3s linear infinite;
|
||||
/* Chrome, Opera 15+, Safari 5+ */
|
||||
-ms-animation: spin 3s linear infinite;
|
||||
/* Chrome, Opera 15+, Safari 5+ */
|
||||
animation: spin 3s linear infinite;
|
||||
/* Chrome, Firefox 16+, IE 10+, Opera */
|
||||
}
|
||||
|
||||
#loader:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
left: 15px;
|
||||
right: 15px;
|
||||
bottom: 15px;
|
||||
border-radius: 50%;
|
||||
border: 3px solid transparent;
|
||||
border-top-color: #165dff;
|
||||
/* COLOR 3 */
|
||||
-moz-animation: spin 1.5s linear infinite;
|
||||
/* Chrome, Opera 15+, Safari 5+ */
|
||||
-o-animation: spin 1.5s linear infinite;
|
||||
/* Chrome, Opera 15+, Safari 5+ */
|
||||
-ms-animation: spin 1.5s linear infinite;
|
||||
/* Chrome, Opera 15+, Safari 5+ */
|
||||
-webkit-animation: spin 1.5s linear infinite;
|
||||
/* Chrome, Opera 15+, Safari 5+ */
|
||||
animation: spin 1.5s linear infinite;
|
||||
/* Chrome, Firefox 16+, IE 10+, Opera */
|
||||
}
|
||||
|
||||
@-webkit-keyframes spin {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
/* Chrome, Opera 15+, Safari 3.1+ */
|
||||
-ms-transform: rotate(0deg);
|
||||
/* IE 9 */
|
||||
transform: rotate(0deg);
|
||||
/* Firefox 16+, IE 10+, Opera */
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
/* Chrome, Opera 15+, Safari 3.1+ */
|
||||
-ms-transform: rotate(360deg);
|
||||
/* IE 9 */
|
||||
transform: rotate(360deg);
|
||||
/* Firefox 16+, IE 10+, Opera */
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
/* Chrome, Opera 15+, Safari 3.1+ */
|
||||
-ms-transform: rotate(0deg);
|
||||
/* IE 9 */
|
||||
transform: rotate(0deg);
|
||||
/* Firefox 16+, IE 10+, Opera */
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
/* Chrome, Opera 15+, Safari 3.1+ */
|
||||
-ms-transform: rotate(360deg);
|
||||
/* IE 9 */
|
||||
transform: rotate(360deg);
|
||||
/* Firefox 16+, IE 10+, Opera */
|
||||
}
|
||||
}
|
||||
|
||||
#loader-wrapper .loader-section {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
width: 51%;
|
||||
height: 100%;
|
||||
background: #fff;
|
||||
/* Old browsers */
|
||||
z-index: 1000;
|
||||
-webkit-transform: translateX(0);
|
||||
/* Chrome, Opera 15+, Safari 3.1+ */
|
||||
-ms-transform: translateX(0);
|
||||
/* IE 9 */
|
||||
transform: translateX(0);
|
||||
/* Firefox 16+, IE 10+, Opera */
|
||||
}
|
||||
|
||||
#loader-wrapper .loader-section.section-left {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
#loader-wrapper .loader-section.section-right {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
/* Loaded */
|
||||
|
||||
.loaded #loader-wrapper .loader-section.section-left {
|
||||
-webkit-transform: translateX(-100%);
|
||||
/* Chrome, Opera 15+, Safari 3.1+ */
|
||||
-ms-transform: translateX(-100%);
|
||||
/* IE 9 */
|
||||
transform: translateX(-100%);
|
||||
/* Firefox 16+, IE 10+, Opera */
|
||||
-webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
|
||||
transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
|
||||
}
|
||||
|
||||
.loaded #loader-wrapper .loader-section.section-right {
|
||||
-webkit-transform: translateX(100%);
|
||||
/* Chrome, Opera 15+, Safari 3.1+ */
|
||||
-ms-transform: translateX(100%);
|
||||
/* IE 9 */
|
||||
transform: translateX(100%);
|
||||
/* Firefox 16+, IE 10+, Opera */
|
||||
-webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
|
||||
transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
|
||||
}
|
||||
|
||||
.loaded #loader {
|
||||
opacity: 0;
|
||||
-webkit-transition: all 0.3s ease-out;
|
||||
transition: all 0.3s ease-out;
|
||||
}
|
||||
|
||||
.loaded #loader-wrapper {
|
||||
visibility: hidden;
|
||||
-webkit-transform: translateY(-100%);
|
||||
/* Chrome, Opera 15+, Safari 3.1+ */
|
||||
-ms-transform: translateY(-100%);
|
||||
/* IE 9 */
|
||||
transform: translateY(-100%);
|
||||
/* Firefox 16+, IE 10+, Opera */
|
||||
-webkit-transition: all 0.3s 1s ease-out;
|
||||
transition: all 0.3s 1s ease-out;
|
||||
}
|
||||
|
||||
/* JavaScript Turned Off */
|
||||
|
||||
.no-js #loader-wrapper {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.no-js h1 {
|
||||
color: #222222;
|
||||
}
|
||||
|
||||
#loader-wrapper .load_title {
|
||||
font-family: 'Open Sans', serif;
|
||||
color: #165dff;
|
||||
font-size: 19px;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
z-index: 9999999999999;
|
||||
position: absolute;
|
||||
top: 48%;
|
||||
opacity: 1;
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
#loader-wrapper .load_title span {
|
||||
font-weight: normal;
|
||||
font-style: italic;
|
||||
font-size: 13px;
|
||||
color: #165dff;
|
||||
opacity: 0.5;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
<strong>您的浏览器未开启或不支持JavaScript.</strong>
|
||||
</noscript>
|
||||
<div id="app">
|
||||
<div id="loader-wrapper">
|
||||
<div id="loader"></div>
|
||||
<div class="loader-section section-left"></div>
|
||||
<div class="loader-section section-right"></div>
|
||||
<div class="load_title">FxBoot</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
<script>
|
||||
window.onload = function () {
|
||||
var lastTouchEnd = 0
|
||||
document.addEventListener('touchstart', function (event) {
|
||||
if (event.touches.length > 1) {
|
||||
event.preventDefault()
|
||||
}
|
||||
})
|
||||
document.addEventListener(
|
||||
'touchend',
|
||||
function (event) {
|
||||
var now = new Date().getTime()
|
||||
|
||||
if (now - lastTouchEnd <= 300) {
|
||||
event.preventDefault()
|
||||
}
|
||||
|
||||
lastTouchEnd = now
|
||||
},
|
||||
false
|
||||
)
|
||||
document.addEventListener('gesturestart', function (event) {
|
||||
event.preventDefault()
|
||||
})
|
||||
document.addEventListener('dblclick', function (event) {
|
||||
event.preventDefault()
|
||||
})
|
||||
}
|
||||
</script>
|
||||
</html>
|
71
package.json
Normal file
71
package.json
Normal file
@ -0,0 +1,71 @@
|
||||
{
|
||||
"name": "fxboot-ui",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"license": "ISC",
|
||||
"packageManager": "pnpm@9.7.0",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite optimize && vite build",
|
||||
"type-check": "vite optimize && vue-tsc --noEmit --project tsconfig.json --strict",
|
||||
"serve": "vite preview",
|
||||
"prepare": "husky install",
|
||||
"commit": "npx cz-customizable",
|
||||
"cz": "npx cz-customizable"
|
||||
},
|
||||
"dependencies": {
|
||||
"@icon-park/vue-next": "^1.4.2",
|
||||
"@vueuse/core": "^9.13.0",
|
||||
"axios": "^1.6.8",
|
||||
"crypto-js": "^4.1.1",
|
||||
"dayjs": "^1.11.3",
|
||||
"decimal.js": "^10.4.3",
|
||||
"encryptlong": "^3.1.4",
|
||||
"jsencrypt": "^3.2.1",
|
||||
"lodash": "^4.17.21",
|
||||
"pinia": "~2.0.14",
|
||||
"qs": "~6.10.1",
|
||||
"vue": "~3.2.37",
|
||||
"vue-router": "~4.0.16",
|
||||
"xlsx": "^0.18.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@arco-design/web-vue": "~2.55.1",
|
||||
"@commitlint/cli": "~17.3.0",
|
||||
"@commitlint/config-conventional": "~17.3.0",
|
||||
"@iconify/json": "^2.2.144",
|
||||
"@types/lodash": "^4.14.180",
|
||||
"@types/node": "~16.11.11",
|
||||
"@typescript-eslint/eslint-plugin": "~4.33.0",
|
||||
"@typescript-eslint/parser": "~4.33.0",
|
||||
"@vitejs/plugin-vue": "^3.0.0",
|
||||
"@vitejs/plugin-vue-jsx": "^2.0.0",
|
||||
"autoprefixer": "^10.4.13",
|
||||
"crco": "2.9.14",
|
||||
"cz-customizable": "~7.0.0",
|
||||
"eslint": "~7.32.0",
|
||||
"eslint-config-airbnb-base": "~14.2.1",
|
||||
"eslint-config-prettier": "~8.3.0",
|
||||
"eslint-plugin-import": "~2.25.3",
|
||||
"eslint-plugin-prettier": "~4.0.0",
|
||||
"eslint-plugin-vue": "~7.20.0",
|
||||
"husky": "~8.0.2",
|
||||
"less": "^4.1.2",
|
||||
"lint-staged": "~12.3.7",
|
||||
"postcss": "^8.4.21",
|
||||
"prettier": "~2.6.0",
|
||||
"prettier-plugin-tailwindcss": "^0.2.4",
|
||||
"sass": "~1.49.9",
|
||||
"tailwindcss": "^3.2.7",
|
||||
"terser": "^5.14.2",
|
||||
"typescript": "~4.4.4",
|
||||
"unplugin-auto-import": "^0.16.7",
|
||||
"unplugin-vue-components": "^0.25.2",
|
||||
"vite": "^3.0.0",
|
||||
"vite-plugin-compression": "^0.5.1",
|
||||
"vue-tsc": "~0.3.0"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{vue,js,jsx,ts,tsx}": "eslint --fix"
|
||||
}
|
||||
}
|
6477
pnpm-lock.yaml
generated
Normal file
6477
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
6
postcss.config.js
Normal file
6
postcss.config.js
Normal file
@ -0,0 +1,6 @@
|
||||
module.exports = {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {}
|
||||
}
|
||||
}
|
BIN
public/bg.jpeg
Normal file
BIN
public/bg.jpeg
Normal file
Binary file not shown.
After Width: | Height: | Size: 465 KiB |
BIN
public/bg_small.jpeg
Normal file
BIN
public/bg_small.jpeg
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.2 KiB |
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
7
public/font-awesome-4.7.0/HELP-US-OUT.txt
Normal file
7
public/font-awesome-4.7.0/HELP-US-OUT.txt
Normal file
@ -0,0 +1,7 @@
|
||||
I hope you love Font Awesome. If you've found it useful, please do me a favor and check out my latest project,
|
||||
Fort Awesome (https://fortawesome.com). It makes it easy to put the perfect icons on your website. Choose from our awesome,
|
||||
comprehensive icon sets or copy and paste your own.
|
||||
|
||||
Please. Check it out.
|
||||
|
||||
-Dave Gandy
|
2341
public/font-awesome-4.7.0/css/font-awesome.css
vendored
Normal file
2341
public/font-awesome-4.7.0/css/font-awesome.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2335
public/font-awesome-4.7.0/css/font-awesome.min.css
vendored
Normal file
2335
public/font-awesome-4.7.0/css/font-awesome.min.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
BIN
public/font-awesome-4.7.0/fonts/FontAwesome.otf
Normal file
BIN
public/font-awesome-4.7.0/fonts/FontAwesome.otf
Normal file
Binary file not shown.
BIN
public/font-awesome-4.7.0/fonts/fontawesome-webfont.eot
Normal file
BIN
public/font-awesome-4.7.0/fonts/fontawesome-webfont.eot
Normal file
Binary file not shown.
2671
public/font-awesome-4.7.0/fonts/fontawesome-webfont.svg
Normal file
2671
public/font-awesome-4.7.0/fonts/fontawesome-webfont.svg
Normal file
File diff suppressed because it is too large
Load Diff
After Width: | Height: | Size: 434 KiB |
BIN
public/font-awesome-4.7.0/fonts/fontawesome-webfont.ttf
Normal file
BIN
public/font-awesome-4.7.0/fonts/fontawesome-webfont.ttf
Normal file
Binary file not shown.
BIN
public/font-awesome-4.7.0/fonts/fontawesome-webfont.woff
Normal file
BIN
public/font-awesome-4.7.0/fonts/fontawesome-webfont.woff
Normal file
Binary file not shown.
BIN
public/font-awesome-4.7.0/fonts/fontawesome-webfont.woff2
Normal file
BIN
public/font-awesome-4.7.0/fonts/fontawesome-webfont.woff2
Normal file
Binary file not shown.
34
public/font-awesome-4.7.0/less/animated.less
Normal file
34
public/font-awesome-4.7.0/less/animated.less
Normal file
@ -0,0 +1,34 @@
|
||||
// Animated Icons
|
||||
// --------------------------
|
||||
|
||||
.@{fa-css-prefix}-spin {
|
||||
-webkit-animation: fa-spin 2s infinite linear;
|
||||
animation: fa-spin 2s infinite linear;
|
||||
}
|
||||
|
||||
.@{fa-css-prefix}-pulse {
|
||||
-webkit-animation: fa-spin 1s infinite steps(8);
|
||||
animation: fa-spin 1s infinite steps(8);
|
||||
}
|
||||
|
||||
@-webkit-keyframes fa-spin {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: rotate(359deg);
|
||||
transform: rotate(359deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fa-spin {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: rotate(359deg);
|
||||
transform: rotate(359deg);
|
||||
}
|
||||
}
|
41
public/font-awesome-4.7.0/less/bordered-pulled.less
Normal file
41
public/font-awesome-4.7.0/less/bordered-pulled.less
Normal file
@ -0,0 +1,41 @@
|
||||
// Bordered & Pulled
|
||||
// -------------------------
|
||||
|
||||
.@{fa-css-prefix}-border {
|
||||
padding: 0.2em 0.25em 0.15em;
|
||||
border: solid 0.08em @fa-border-color;
|
||||
border-radius: 0.1em;
|
||||
}
|
||||
|
||||
.@{fa-css-prefix}-pull-left {
|
||||
float: left;
|
||||
}
|
||||
.@{fa-css-prefix}-pull-right {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.@{fa-css-prefix} {
|
||||
&.@{fa-css-prefix}-pull-left {
|
||||
margin-right: 0.3em;
|
||||
}
|
||||
&.@{fa-css-prefix}-pull-right {
|
||||
margin-left: 0.3em;
|
||||
}
|
||||
}
|
||||
|
||||
/* Deprecated as of 4.4.0 */
|
||||
.pull-right {
|
||||
float: right;
|
||||
}
|
||||
.pull-left {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.@{fa-css-prefix} {
|
||||
&.pull-left {
|
||||
margin-right: 0.3em;
|
||||
}
|
||||
&.pull-right {
|
||||
margin-left: 0.3em;
|
||||
}
|
||||
}
|
11
public/font-awesome-4.7.0/less/core.less
Normal file
11
public/font-awesome-4.7.0/less/core.less
Normal file
@ -0,0 +1,11 @@
|
||||
// Base Class Definition
|
||||
// -------------------------
|
||||
|
||||
.@{fa-css-prefix} {
|
||||
display: inline-block;
|
||||
font: normal normal normal @fa-font-size-base / @fa-line-height-base FontAwesome; // shortening font declaration
|
||||
font-size: inherit; // can't have font-size inherit on line above, so need to override
|
||||
text-rendering: auto; // optimizelegibility throws things off #1094
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
6
public/font-awesome-4.7.0/less/fixed-width.less
Normal file
6
public/font-awesome-4.7.0/less/fixed-width.less
Normal file
@ -0,0 +1,6 @@
|
||||
// Fixed Width Icons
|
||||
// -------------------------
|
||||
.@{fa-css-prefix}-fw {
|
||||
width: (18em / 14);
|
||||
text-align: center;
|
||||
}
|
18
public/font-awesome-4.7.0/less/font-awesome.less
vendored
Normal file
18
public/font-awesome-4.7.0/less/font-awesome.less
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
/*!
|
||||
* Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome
|
||||
* License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
|
||||
*/
|
||||
|
||||
@import 'variables.less';
|
||||
@import 'mixins.less';
|
||||
@import 'path.less';
|
||||
@import 'core.less';
|
||||
@import 'larger.less';
|
||||
@import 'fixed-width.less';
|
||||
@import 'list.less';
|
||||
@import 'bordered-pulled.less';
|
||||
@import 'animated.less';
|
||||
@import 'rotated-flipped.less';
|
||||
@import 'stacked.less';
|
||||
@import 'icons.less';
|
||||
@import 'screen-reader.less';
|
2139
public/font-awesome-4.7.0/less/icons.less
Normal file
2139
public/font-awesome-4.7.0/less/icons.less
Normal file
File diff suppressed because it is too large
Load Diff
21
public/font-awesome-4.7.0/less/larger.less
Normal file
21
public/font-awesome-4.7.0/less/larger.less
Normal file
@ -0,0 +1,21 @@
|
||||
// Icon Sizes
|
||||
// -------------------------
|
||||
|
||||
/* makes the font 33% larger relative to the icon container */
|
||||
.@{fa-css-prefix}-lg {
|
||||
font-size: (4em / 3);
|
||||
line-height: (3em / 4);
|
||||
vertical-align: -15%;
|
||||
}
|
||||
.@{fa-css-prefix}-2x {
|
||||
font-size: 2em;
|
||||
}
|
||||
.@{fa-css-prefix}-3x {
|
||||
font-size: 3em;
|
||||
}
|
||||
.@{fa-css-prefix}-4x {
|
||||
font-size: 4em;
|
||||
}
|
||||
.@{fa-css-prefix}-5x {
|
||||
font-size: 5em;
|
||||
}
|
21
public/font-awesome-4.7.0/less/list.less
Normal file
21
public/font-awesome-4.7.0/less/list.less
Normal file
@ -0,0 +1,21 @@
|
||||
// List Icons
|
||||
// -------------------------
|
||||
|
||||
.@{fa-css-prefix}-ul {
|
||||
padding-left: 0;
|
||||
margin-left: @fa-li-width;
|
||||
list-style-type: none;
|
||||
> li {
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
.@{fa-css-prefix}-li {
|
||||
position: absolute;
|
||||
left: -@fa-li-width;
|
||||
width: @fa-li-width;
|
||||
top: (2em / 14);
|
||||
text-align: center;
|
||||
&.@{fa-css-prefix}-lg {
|
||||
left: (-@fa-li-width + (4em / 14));
|
||||
}
|
||||
}
|
58
public/font-awesome-4.7.0/less/mixins.less
Normal file
58
public/font-awesome-4.7.0/less/mixins.less
Normal file
@ -0,0 +1,58 @@
|
||||
// Mixins
|
||||
// --------------------------
|
||||
|
||||
.fa-icon() {
|
||||
display: inline-block;
|
||||
font: normal normal normal @fa-font-size-base / @fa-line-height-base FontAwesome; // shortening font declaration
|
||||
font-size: inherit; // can't have font-size inherit on line above, so need to override
|
||||
text-rendering: auto; // optimizelegibility throws things off #1094
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.fa-icon-rotate(@degrees, @rotation) {
|
||||
-ms-filter: 'progid:DXImageTransform.Microsoft.BasicImage(rotation=@{rotation})';
|
||||
-webkit-transform: rotate(@degrees);
|
||||
-ms-transform: rotate(@degrees);
|
||||
transform: rotate(@degrees);
|
||||
}
|
||||
|
||||
.fa-icon-flip(@horiz, @vert, @rotation) {
|
||||
-ms-filter: 'progid:DXImageTransform.Microsoft.BasicImage(rotation=@{rotation}, mirror=1)';
|
||||
-webkit-transform: scale(@horiz, @vert);
|
||||
-ms-transform: scale(@horiz, @vert);
|
||||
transform: scale(@horiz, @vert);
|
||||
}
|
||||
|
||||
// Only display content to screen readers. A la Bootstrap 4.
|
||||
//
|
||||
// See: http://a11yproject.com/posts/how-to-hide-content/
|
||||
|
||||
.sr-only() {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
border: 0;
|
||||
}
|
||||
|
||||
// Use in conjunction with .sr-only to only display content when it's focused.
|
||||
//
|
||||
// Useful for "Skip to main content" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1
|
||||
//
|
||||
// Credit: HTML5 Boilerplate
|
||||
|
||||
.sr-only-focusable() {
|
||||
&:active,
|
||||
&:focus {
|
||||
position: static;
|
||||
width: auto;
|
||||
height: auto;
|
||||
margin: 0;
|
||||
overflow: visible;
|
||||
clip: auto;
|
||||
}
|
||||
}
|
16
public/font-awesome-4.7.0/less/path.less
Normal file
16
public/font-awesome-4.7.0/less/path.less
Normal file
@ -0,0 +1,16 @@
|
||||
/* FONT PATH
|
||||
* -------------------------- */
|
||||
|
||||
@font-face {
|
||||
font-family: 'FontAwesome';
|
||||
src: url('@{fa-font-path}/fontawesome-webfont.eot?v=@{fa-version}');
|
||||
src: url('@{fa-font-path}/fontawesome-webfont.eot?#iefix&v=@{fa-version}')
|
||||
format('embedded-opentype'),
|
||||
url('@{fa-font-path}/fontawesome-webfont.woff2?v=@{fa-version}') format('woff2'),
|
||||
url('@{fa-font-path}/fontawesome-webfont.woff?v=@{fa-version}') format('woff'),
|
||||
url('@{fa-font-path}/fontawesome-webfont.ttf?v=@{fa-version}') format('truetype'),
|
||||
url('@{fa-font-path}/fontawesome-webfont.svg?v=@{fa-version}#fontawesomeregular') format('svg');
|
||||
// src: url('@{fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
30
public/font-awesome-4.7.0/less/rotated-flipped.less
Normal file
30
public/font-awesome-4.7.0/less/rotated-flipped.less
Normal file
@ -0,0 +1,30 @@
|
||||
// Rotated & Flipped Icons
|
||||
// -------------------------
|
||||
|
||||
.@{fa-css-prefix}-rotate-90 {
|
||||
.fa-icon-rotate(90deg, 1);
|
||||
}
|
||||
.@{fa-css-prefix}-rotate-180 {
|
||||
.fa-icon-rotate(180deg, 2);
|
||||
}
|
||||
.@{fa-css-prefix}-rotate-270 {
|
||||
.fa-icon-rotate(270deg, 3);
|
||||
}
|
||||
|
||||
.@{fa-css-prefix}-flip-horizontal {
|
||||
.fa-icon-flip(-1, 1, 0);
|
||||
}
|
||||
.@{fa-css-prefix}-flip-vertical {
|
||||
.fa-icon-flip(1, -1, 2);
|
||||
}
|
||||
|
||||
// Hook for IE8-9
|
||||
// -------------------------
|
||||
|
||||
:root .@{fa-css-prefix}-rotate-90,
|
||||
:root .@{fa-css-prefix}-rotate-180,
|
||||
:root .@{fa-css-prefix}-rotate-270,
|
||||
:root .@{fa-css-prefix}-flip-horizontal,
|
||||
:root .@{fa-css-prefix}-flip-vertical {
|
||||
filter: none;
|
||||
}
|
9
public/font-awesome-4.7.0/less/screen-reader.less
Normal file
9
public/font-awesome-4.7.0/less/screen-reader.less
Normal file
@ -0,0 +1,9 @@
|
||||
// Screen Readers
|
||||
// -------------------------
|
||||
|
||||
.sr-only {
|
||||
.sr-only();
|
||||
}
|
||||
.sr-only-focusable {
|
||||
.sr-only-focusable();
|
||||
}
|
27
public/font-awesome-4.7.0/less/stacked.less
Normal file
27
public/font-awesome-4.7.0/less/stacked.less
Normal file
@ -0,0 +1,27 @@
|
||||
// Stacked Icons
|
||||
// -------------------------
|
||||
|
||||
.@{fa-css-prefix}-stack {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 2em;
|
||||
height: 2em;
|
||||
line-height: 2em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.@{fa-css-prefix}-stack-1x,
|
||||
.@{fa-css-prefix}-stack-2x {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
.@{fa-css-prefix}-stack-1x {
|
||||
line-height: inherit;
|
||||
}
|
||||
.@{fa-css-prefix}-stack-2x {
|
||||
font-size: 2em;
|
||||
}
|
||||
.@{fa-css-prefix}-inverse {
|
||||
color: @fa-inverse;
|
||||
}
|
799
public/font-awesome-4.7.0/less/variables.less
Normal file
799
public/font-awesome-4.7.0/less/variables.less
Normal file
@ -0,0 +1,799 @@
|
||||
// Variables
|
||||
// --------------------------
|
||||
|
||||
@fa-font-path: '../fonts';
|
||||
@fa-font-size-base: 14px;
|
||||
@fa-line-height-base: 1;
|
||||
//@fa-font-path: "//netdna.bootstrapcdn.com/font-awesome/4.7.0/fonts"; // for referencing Bootstrap CDN font files directly
|
||||
@fa-css-prefix: fa;
|
||||
@fa-version: '4.7.0';
|
||||
@fa-border-color: #eee;
|
||||
@fa-inverse: #fff;
|
||||
@fa-li-width: (30em / 14);
|
||||
|
||||
@fa-var-500px: '\f26e';
|
||||
@fa-var-address-book: '\f2b9';
|
||||
@fa-var-address-book-o: '\f2ba';
|
||||
@fa-var-address-card: '\f2bb';
|
||||
@fa-var-address-card-o: '\f2bc';
|
||||
@fa-var-adjust: '\f042';
|
||||
@fa-var-adn: '\f170';
|
||||
@fa-var-align-center: '\f037';
|
||||
@fa-var-align-justify: '\f039';
|
||||
@fa-var-align-left: '\f036';
|
||||
@fa-var-align-right: '\f038';
|
||||
@fa-var-amazon: '\f270';
|
||||
@fa-var-ambulance: '\f0f9';
|
||||
@fa-var-american-sign-language-interpreting: '\f2a3';
|
||||
@fa-var-anchor: '\f13d';
|
||||
@fa-var-android: '\f17b';
|
||||
@fa-var-angellist: '\f209';
|
||||
@fa-var-angle-double-down: '\f103';
|
||||
@fa-var-angle-double-left: '\f100';
|
||||
@fa-var-angle-double-right: '\f101';
|
||||
@fa-var-angle-double-up: '\f102';
|
||||
@fa-var-angle-down: '\f107';
|
||||
@fa-var-angle-left: '\f104';
|
||||
@fa-var-angle-right: '\f105';
|
||||
@fa-var-angle-up: '\f106';
|
||||
@fa-var-apple: '\f179';
|
||||
@fa-var-archive: '\f187';
|
||||
@fa-var-area-chart: '\f1fe';
|
||||
@fa-var-arrow-circle-down: '\f0ab';
|
||||
@fa-var-arrow-circle-left: '\f0a8';
|
||||
@fa-var-arrow-circle-o-down: '\f01a';
|
||||
@fa-var-arrow-circle-o-left: '\f190';
|
||||
@fa-var-arrow-circle-o-right: '\f18e';
|
||||
@fa-var-arrow-circle-o-up: '\f01b';
|
||||
@fa-var-arrow-circle-right: '\f0a9';
|
||||
@fa-var-arrow-circle-up: '\f0aa';
|
||||
@fa-var-arrow-down: '\f063';
|
||||
@fa-var-arrow-left: '\f060';
|
||||
@fa-var-arrow-right: '\f061';
|
||||
@fa-var-arrow-up: '\f062';
|
||||
@fa-var-arrows: '\f047';
|
||||
@fa-var-arrows-alt: '\f0b2';
|
||||
@fa-var-arrows-h: '\f07e';
|
||||
@fa-var-arrows-v: '\f07d';
|
||||
@fa-var-asl-interpreting: '\f2a3';
|
||||
@fa-var-assistive-listening-systems: '\f2a2';
|
||||
@fa-var-asterisk: '\f069';
|
||||
@fa-var-at: '\f1fa';
|
||||
@fa-var-audio-description: '\f29e';
|
||||
@fa-var-automobile: '\f1b9';
|
||||
@fa-var-backward: '\f04a';
|
||||
@fa-var-balance-scale: '\f24e';
|
||||
@fa-var-ban: '\f05e';
|
||||
@fa-var-bandcamp: '\f2d5';
|
||||
@fa-var-bank: '\f19c';
|
||||
@fa-var-bar-chart: '\f080';
|
||||
@fa-var-bar-chart-o: '\f080';
|
||||
@fa-var-barcode: '\f02a';
|
||||
@fa-var-bars: '\f0c9';
|
||||
@fa-var-bath: '\f2cd';
|
||||
@fa-var-bathtub: '\f2cd';
|
||||
@fa-var-battery: '\f240';
|
||||
@fa-var-battery-0: '\f244';
|
||||
@fa-var-battery-1: '\f243';
|
||||
@fa-var-battery-2: '\f242';
|
||||
@fa-var-battery-3: '\f241';
|
||||
@fa-var-battery-4: '\f240';
|
||||
@fa-var-battery-empty: '\f244';
|
||||
@fa-var-battery-full: '\f240';
|
||||
@fa-var-battery-half: '\f242';
|
||||
@fa-var-battery-quarter: '\f243';
|
||||
@fa-var-battery-three-quarters: '\f241';
|
||||
@fa-var-bed: '\f236';
|
||||
@fa-var-beer: '\f0fc';
|
||||
@fa-var-behance: '\f1b4';
|
||||
@fa-var-behance-square: '\f1b5';
|
||||
@fa-var-bell: '\f0f3';
|
||||
@fa-var-bell-o: '\f0a2';
|
||||
@fa-var-bell-slash: '\f1f6';
|
||||
@fa-var-bell-slash-o: '\f1f7';
|
||||
@fa-var-bicycle: '\f206';
|
||||
@fa-var-binoculars: '\f1e5';
|
||||
@fa-var-birthday-cake: '\f1fd';
|
||||
@fa-var-bitbucket: '\f171';
|
||||
@fa-var-bitbucket-square: '\f172';
|
||||
@fa-var-bitcoin: '\f15a';
|
||||
@fa-var-black-tie: '\f27e';
|
||||
@fa-var-blind: '\f29d';
|
||||
@fa-var-bluetooth: '\f293';
|
||||
@fa-var-bluetooth-b: '\f294';
|
||||
@fa-var-bold: '\f032';
|
||||
@fa-var-bolt: '\f0e7';
|
||||
@fa-var-bomb: '\f1e2';
|
||||
@fa-var-book: '\f02d';
|
||||
@fa-var-bookmark: '\f02e';
|
||||
@fa-var-bookmark-o: '\f097';
|
||||
@fa-var-braille: '\f2a1';
|
||||
@fa-var-briefcase: '\f0b1';
|
||||
@fa-var-btc: '\f15a';
|
||||
@fa-var-bug: '\f188';
|
||||
@fa-var-building: '\f1ad';
|
||||
@fa-var-building-o: '\f0f7';
|
||||
@fa-var-bullhorn: '\f0a1';
|
||||
@fa-var-bullseye: '\f140';
|
||||
@fa-var-bus: '\f207';
|
||||
@fa-var-buysellads: '\f20d';
|
||||
@fa-var-cab: '\f1ba';
|
||||
@fa-var-calculator: '\f1ec';
|
||||
@fa-var-calendar: '\f073';
|
||||
@fa-var-calendar-check-o: '\f274';
|
||||
@fa-var-calendar-minus-o: '\f272';
|
||||
@fa-var-calendar-o: '\f133';
|
||||
@fa-var-calendar-plus-o: '\f271';
|
||||
@fa-var-calendar-times-o: '\f273';
|
||||
@fa-var-camera: '\f030';
|
||||
@fa-var-camera-retro: '\f083';
|
||||
@fa-var-car: '\f1b9';
|
||||
@fa-var-caret-down: '\f0d7';
|
||||
@fa-var-caret-left: '\f0d9';
|
||||
@fa-var-caret-right: '\f0da';
|
||||
@fa-var-caret-square-o-down: '\f150';
|
||||
@fa-var-caret-square-o-left: '\f191';
|
||||
@fa-var-caret-square-o-right: '\f152';
|
||||
@fa-var-caret-square-o-up: '\f151';
|
||||
@fa-var-caret-up: '\f0d8';
|
||||
@fa-var-cart-arrow-down: '\f218';
|
||||
@fa-var-cart-plus: '\f217';
|
||||
@fa-var-cc: '\f20a';
|
||||
@fa-var-cc-amex: '\f1f3';
|
||||
@fa-var-cc-diners-club: '\f24c';
|
||||
@fa-var-cc-discover: '\f1f2';
|
||||
@fa-var-cc-jcb: '\f24b';
|
||||
@fa-var-cc-mastercard: '\f1f1';
|
||||
@fa-var-cc-paypal: '\f1f4';
|
||||
@fa-var-cc-stripe: '\f1f5';
|
||||
@fa-var-cc-visa: '\f1f0';
|
||||
@fa-var-certificate: '\f0a3';
|
||||
@fa-var-chain: '\f0c1';
|
||||
@fa-var-chain-broken: '\f127';
|
||||
@fa-var-check: '\f00c';
|
||||
@fa-var-check-circle: '\f058';
|
||||
@fa-var-check-circle-o: '\f05d';
|
||||
@fa-var-check-square: '\f14a';
|
||||
@fa-var-check-square-o: '\f046';
|
||||
@fa-var-chevron-circle-down: '\f13a';
|
||||
@fa-var-chevron-circle-left: '\f137';
|
||||
@fa-var-chevron-circle-right: '\f138';
|
||||
@fa-var-chevron-circle-up: '\f139';
|
||||
@fa-var-chevron-down: '\f078';
|
||||
@fa-var-chevron-left: '\f053';
|
||||
@fa-var-chevron-right: '\f054';
|
||||
@fa-var-chevron-up: '\f077';
|
||||
@fa-var-child: '\f1ae';
|
||||
@fa-var-chrome: '\f268';
|
||||
@fa-var-circle: '\f111';
|
||||
@fa-var-circle-o: '\f10c';
|
||||
@fa-var-circle-o-notch: '\f1ce';
|
||||
@fa-var-circle-thin: '\f1db';
|
||||
@fa-var-clipboard: '\f0ea';
|
||||
@fa-var-clock-o: '\f017';
|
||||
@fa-var-clone: '\f24d';
|
||||
@fa-var-close: '\f00d';
|
||||
@fa-var-cloud: '\f0c2';
|
||||
@fa-var-cloud-download: '\f0ed';
|
||||
@fa-var-cloud-upload: '\f0ee';
|
||||
@fa-var-cny: '\f157';
|
||||
@fa-var-code: '\f121';
|
||||
@fa-var-code-fork: '\f126';
|
||||
@fa-var-codepen: '\f1cb';
|
||||
@fa-var-codiepie: '\f284';
|
||||
@fa-var-coffee: '\f0f4';
|
||||
@fa-var-cog: '\f013';
|
||||
@fa-var-cogs: '\f085';
|
||||
@fa-var-columns: '\f0db';
|
||||
@fa-var-comment: '\f075';
|
||||
@fa-var-comment-o: '\f0e5';
|
||||
@fa-var-commenting: '\f27a';
|
||||
@fa-var-commenting-o: '\f27b';
|
||||
@fa-var-comments: '\f086';
|
||||
@fa-var-comments-o: '\f0e6';
|
||||
@fa-var-compass: '\f14e';
|
||||
@fa-var-compress: '\f066';
|
||||
@fa-var-connectdevelop: '\f20e';
|
||||
@fa-var-contao: '\f26d';
|
||||
@fa-var-copy: '\f0c5';
|
||||
@fa-var-copyright: '\f1f9';
|
||||
@fa-var-creative-commons: '\f25e';
|
||||
@fa-var-credit-card: '\f09d';
|
||||
@fa-var-credit-card-alt: '\f283';
|
||||
@fa-var-crop: '\f125';
|
||||
@fa-var-crosshairs: '\f05b';
|
||||
@fa-var-css3: '\f13c';
|
||||
@fa-var-cube: '\f1b2';
|
||||
@fa-var-cubes: '\f1b3';
|
||||
@fa-var-cut: '\f0c4';
|
||||
@fa-var-cutlery: '\f0f5';
|
||||
@fa-var-dashboard: '\f0e4';
|
||||
@fa-var-dashcube: '\f210';
|
||||
@fa-var-database: '\f1c0';
|
||||
@fa-var-deaf: '\f2a4';
|
||||
@fa-var-deafness: '\f2a4';
|
||||
@fa-var-dedent: '\f03b';
|
||||
@fa-var-delicious: '\f1a5';
|
||||
@fa-var-desktop: '\f108';
|
||||
@fa-var-deviantart: '\f1bd';
|
||||
@fa-var-diamond: '\f219';
|
||||
@fa-var-digg: '\f1a6';
|
||||
@fa-var-dollar: '\f155';
|
||||
@fa-var-dot-circle-o: '\f192';
|
||||
@fa-var-download: '\f019';
|
||||
@fa-var-dribbble: '\f17d';
|
||||
@fa-var-drivers-license: '\f2c2';
|
||||
@fa-var-drivers-license-o: '\f2c3';
|
||||
@fa-var-dropbox: '\f16b';
|
||||
@fa-var-drupal: '\f1a9';
|
||||
@fa-var-edge: '\f282';
|
||||
@fa-var-edit: '\f044';
|
||||
@fa-var-eercast: '\f2da';
|
||||
@fa-var-eject: '\f052';
|
||||
@fa-var-ellipsis-h: '\f141';
|
||||
@fa-var-ellipsis-v: '\f142';
|
||||
@fa-var-empire: '\f1d1';
|
||||
@fa-var-envelope: '\f0e0';
|
||||
@fa-var-envelope-o: '\f003';
|
||||
@fa-var-envelope-open: '\f2b6';
|
||||
@fa-var-envelope-open-o: '\f2b7';
|
||||
@fa-var-envelope-square: '\f199';
|
||||
@fa-var-envira: '\f299';
|
||||
@fa-var-eraser: '\f12d';
|
||||
@fa-var-etsy: '\f2d7';
|
||||
@fa-var-eur: '\f153';
|
||||
@fa-var-euro: '\f153';
|
||||
@fa-var-exchange: '\f0ec';
|
||||
@fa-var-exclamation: '\f12a';
|
||||
@fa-var-exclamation-circle: '\f06a';
|
||||
@fa-var-exclamation-triangle: '\f071';
|
||||
@fa-var-expand: '\f065';
|
||||
@fa-var-expeditedssl: '\f23e';
|
||||
@fa-var-external-link: '\f08e';
|
||||
@fa-var-external-link-square: '\f14c';
|
||||
@fa-var-eye: '\f06e';
|
||||
@fa-var-eye-slash: '\f070';
|
||||
@fa-var-eyedropper: '\f1fb';
|
||||
@fa-var-fa: '\f2b4';
|
||||
@fa-var-facebook: '\f09a';
|
||||
@fa-var-facebook-f: '\f09a';
|
||||
@fa-var-facebook-official: '\f230';
|
||||
@fa-var-facebook-square: '\f082';
|
||||
@fa-var-fast-backward: '\f049';
|
||||
@fa-var-fast-forward: '\f050';
|
||||
@fa-var-fax: '\f1ac';
|
||||
@fa-var-feed: '\f09e';
|
||||
@fa-var-female: '\f182';
|
||||
@fa-var-fighter-jet: '\f0fb';
|
||||
@fa-var-file: '\f15b';
|
||||
@fa-var-file-archive-o: '\f1c6';
|
||||
@fa-var-file-audio-o: '\f1c7';
|
||||
@fa-var-file-code-o: '\f1c9';
|
||||
@fa-var-file-excel-o: '\f1c3';
|
||||
@fa-var-file-image-o: '\f1c5';
|
||||
@fa-var-file-movie-o: '\f1c8';
|
||||
@fa-var-file-o: '\f016';
|
||||
@fa-var-file-pdf-o: '\f1c1';
|
||||
@fa-var-file-photo-o: '\f1c5';
|
||||
@fa-var-file-picture-o: '\f1c5';
|
||||
@fa-var-file-powerpoint-o: '\f1c4';
|
||||
@fa-var-file-sound-o: '\f1c7';
|
||||
@fa-var-file-text: '\f15c';
|
||||
@fa-var-file-text-o: '\f0f6';
|
||||
@fa-var-file-video-o: '\f1c8';
|
||||
@fa-var-file-word-o: '\f1c2';
|
||||
@fa-var-file-zip-o: '\f1c6';
|
||||
@fa-var-files-o: '\f0c5';
|
||||
@fa-var-film: '\f008';
|
||||
@fa-var-filter: '\f0b0';
|
||||
@fa-var-fire: '\f06d';
|
||||
@fa-var-fire-extinguisher: '\f134';
|
||||
@fa-var-firefox: '\f269';
|
||||
@fa-var-first-order: '\f2b0';
|
||||
@fa-var-flag: '\f024';
|
||||
@fa-var-flag-checkered: '\f11e';
|
||||
@fa-var-flag-o: '\f11d';
|
||||
@fa-var-flash: '\f0e7';
|
||||
@fa-var-flask: '\f0c3';
|
||||
@fa-var-flickr: '\f16e';
|
||||
@fa-var-floppy-o: '\f0c7';
|
||||
@fa-var-folder: '\f07b';
|
||||
@fa-var-folder-o: '\f114';
|
||||
@fa-var-folder-open: '\f07c';
|
||||
@fa-var-folder-open-o: '\f115';
|
||||
@fa-var-font: '\f031';
|
||||
@fa-var-font-awesome: '\f2b4';
|
||||
@fa-var-fonticons: '\f280';
|
||||
@fa-var-fort-awesome: '\f286';
|
||||
@fa-var-forumbee: '\f211';
|
||||
@fa-var-forward: '\f04e';
|
||||
@fa-var-foursquare: '\f180';
|
||||
@fa-var-free-code-camp: '\f2c5';
|
||||
@fa-var-frown-o: '\f119';
|
||||
@fa-var-futbol-o: '\f1e3';
|
||||
@fa-var-gamepad: '\f11b';
|
||||
@fa-var-gavel: '\f0e3';
|
||||
@fa-var-gbp: '\f154';
|
||||
@fa-var-ge: '\f1d1';
|
||||
@fa-var-gear: '\f013';
|
||||
@fa-var-gears: '\f085';
|
||||
@fa-var-genderless: '\f22d';
|
||||
@fa-var-get-pocket: '\f265';
|
||||
@fa-var-gg: '\f260';
|
||||
@fa-var-gg-circle: '\f261';
|
||||
@fa-var-gift: '\f06b';
|
||||
@fa-var-git: '\f1d3';
|
||||
@fa-var-git-square: '\f1d2';
|
||||
@fa-var-github: '\f09b';
|
||||
@fa-var-github-alt: '\f113';
|
||||
@fa-var-github-square: '\f092';
|
||||
@fa-var-gitlab: '\f296';
|
||||
@fa-var-gittip: '\f184';
|
||||
@fa-var-glass: '\f000';
|
||||
@fa-var-glide: '\f2a5';
|
||||
@fa-var-glide-g: '\f2a6';
|
||||
@fa-var-globe: '\f0ac';
|
||||
@fa-var-google: '\f1a0';
|
||||
@fa-var-google-plus: '\f0d5';
|
||||
@fa-var-google-plus-circle: '\f2b3';
|
||||
@fa-var-google-plus-official: '\f2b3';
|
||||
@fa-var-google-plus-square: '\f0d4';
|
||||
@fa-var-google-wallet: '\f1ee';
|
||||
@fa-var-graduation-cap: '\f19d';
|
||||
@fa-var-gratipay: '\f184';
|
||||
@fa-var-grav: '\f2d6';
|
||||
@fa-var-group: '\f0c0';
|
||||
@fa-var-h-square: '\f0fd';
|
||||
@fa-var-hacker-news: '\f1d4';
|
||||
@fa-var-hand-grab-o: '\f255';
|
||||
@fa-var-hand-lizard-o: '\f258';
|
||||
@fa-var-hand-o-down: '\f0a7';
|
||||
@fa-var-hand-o-left: '\f0a5';
|
||||
@fa-var-hand-o-right: '\f0a4';
|
||||
@fa-var-hand-o-up: '\f0a6';
|
||||
@fa-var-hand-paper-o: '\f256';
|
||||
@fa-var-hand-peace-o: '\f25b';
|
||||
@fa-var-hand-pointer-o: '\f25a';
|
||||
@fa-var-hand-rock-o: '\f255';
|
||||
@fa-var-hand-scissors-o: '\f257';
|
||||
@fa-var-hand-spock-o: '\f259';
|
||||
@fa-var-hand-stop-o: '\f256';
|
||||
@fa-var-handshake-o: '\f2b5';
|
||||
@fa-var-hard-of-hearing: '\f2a4';
|
||||
@fa-var-hashtag: '\f292';
|
||||
@fa-var-hdd-o: '\f0a0';
|
||||
@fa-var-header: '\f1dc';
|
||||
@fa-var-headphones: '\f025';
|
||||
@fa-var-heart: '\f004';
|
||||
@fa-var-heart-o: '\f08a';
|
||||
@fa-var-heartbeat: '\f21e';
|
||||
@fa-var-history: '\f1da';
|
||||
@fa-var-home: '\f015';
|
||||
@fa-var-hospital-o: '\f0f8';
|
||||
@fa-var-hotel: '\f236';
|
||||
@fa-var-hourglass: '\f254';
|
||||
@fa-var-hourglass-1: '\f251';
|
||||
@fa-var-hourglass-2: '\f252';
|
||||
@fa-var-hourglass-3: '\f253';
|
||||
@fa-var-hourglass-end: '\f253';
|
||||
@fa-var-hourglass-half: '\f252';
|
||||
@fa-var-hourglass-o: '\f250';
|
||||
@fa-var-hourglass-start: '\f251';
|
||||
@fa-var-houzz: '\f27c';
|
||||
@fa-var-html5: '\f13b';
|
||||
@fa-var-i-cursor: '\f246';
|
||||
@fa-var-id-badge: '\f2c1';
|
||||
@fa-var-id-card: '\f2c2';
|
||||
@fa-var-id-card-o: '\f2c3';
|
||||
@fa-var-ils: '\f20b';
|
||||
@fa-var-image: '\f03e';
|
||||
@fa-var-imdb: '\f2d8';
|
||||
@fa-var-inbox: '\f01c';
|
||||
@fa-var-indent: '\f03c';
|
||||
@fa-var-industry: '\f275';
|
||||
@fa-var-info: '\f129';
|
||||
@fa-var-info-circle: '\f05a';
|
||||
@fa-var-inr: '\f156';
|
||||
@fa-var-instagram: '\f16d';
|
||||
@fa-var-institution: '\f19c';
|
||||
@fa-var-internet-explorer: '\f26b';
|
||||
@fa-var-intersex: '\f224';
|
||||
@fa-var-ioxhost: '\f208';
|
||||
@fa-var-italic: '\f033';
|
||||
@fa-var-joomla: '\f1aa';
|
||||
@fa-var-jpy: '\f157';
|
||||
@fa-var-jsfiddle: '\f1cc';
|
||||
@fa-var-key: '\f084';
|
||||
@fa-var-keyboard-o: '\f11c';
|
||||
@fa-var-krw: '\f159';
|
||||
@fa-var-language: '\f1ab';
|
||||
@fa-var-laptop: '\f109';
|
||||
@fa-var-lastfm: '\f202';
|
||||
@fa-var-lastfm-square: '\f203';
|
||||
@fa-var-leaf: '\f06c';
|
||||
@fa-var-leanpub: '\f212';
|
||||
@fa-var-legal: '\f0e3';
|
||||
@fa-var-lemon-o: '\f094';
|
||||
@fa-var-level-down: '\f149';
|
||||
@fa-var-level-up: '\f148';
|
||||
@fa-var-life-bouy: '\f1cd';
|
||||
@fa-var-life-buoy: '\f1cd';
|
||||
@fa-var-life-ring: '\f1cd';
|
||||
@fa-var-life-saver: '\f1cd';
|
||||
@fa-var-lightbulb-o: '\f0eb';
|
||||
@fa-var-line-chart: '\f201';
|
||||
@fa-var-link: '\f0c1';
|
||||
@fa-var-linkedin: '\f0e1';
|
||||
@fa-var-linkedin-square: '\f08c';
|
||||
@fa-var-linode: '\f2b8';
|
||||
@fa-var-linux: '\f17c';
|
||||
@fa-var-list: '\f03a';
|
||||
@fa-var-list-alt: '\f022';
|
||||
@fa-var-list-ol: '\f0cb';
|
||||
@fa-var-list-ul: '\f0ca';
|
||||
@fa-var-location-arrow: '\f124';
|
||||
@fa-var-lock: '\f023';
|
||||
@fa-var-long-arrow-down: '\f175';
|
||||
@fa-var-long-arrow-left: '\f177';
|
||||
@fa-var-long-arrow-right: '\f178';
|
||||
@fa-var-long-arrow-up: '\f176';
|
||||
@fa-var-low-vision: '\f2a8';
|
||||
@fa-var-magic: '\f0d0';
|
||||
@fa-var-magnet: '\f076';
|
||||
@fa-var-mail-forward: '\f064';
|
||||
@fa-var-mail-reply: '\f112';
|
||||
@fa-var-mail-reply-all: '\f122';
|
||||
@fa-var-male: '\f183';
|
||||
@fa-var-map: '\f279';
|
||||
@fa-var-map-marker: '\f041';
|
||||
@fa-var-map-o: '\f278';
|
||||
@fa-var-map-pin: '\f276';
|
||||
@fa-var-map-signs: '\f277';
|
||||
@fa-var-mars: '\f222';
|
||||
@fa-var-mars-double: '\f227';
|
||||
@fa-var-mars-stroke: '\f229';
|
||||
@fa-var-mars-stroke-h: '\f22b';
|
||||
@fa-var-mars-stroke-v: '\f22a';
|
||||
@fa-var-maxcdn: '\f136';
|
||||
@fa-var-meanpath: '\f20c';
|
||||
@fa-var-medium: '\f23a';
|
||||
@fa-var-medkit: '\f0fa';
|
||||
@fa-var-meetup: '\f2e0';
|
||||
@fa-var-meh-o: '\f11a';
|
||||
@fa-var-mercury: '\f223';
|
||||
@fa-var-microchip: '\f2db';
|
||||
@fa-var-microphone: '\f130';
|
||||
@fa-var-microphone-slash: '\f131';
|
||||
@fa-var-minus: '\f068';
|
||||
@fa-var-minus-circle: '\f056';
|
||||
@fa-var-minus-square: '\f146';
|
||||
@fa-var-minus-square-o: '\f147';
|
||||
@fa-var-mixcloud: '\f289';
|
||||
@fa-var-mobile: '\f10b';
|
||||
@fa-var-mobile-phone: '\f10b';
|
||||
@fa-var-modx: '\f285';
|
||||
@fa-var-money: '\f0d6';
|
||||
@fa-var-moon-o: '\f186';
|
||||
@fa-var-mortar-board: '\f19d';
|
||||
@fa-var-motorcycle: '\f21c';
|
||||
@fa-var-mouse-pointer: '\f245';
|
||||
@fa-var-music: '\f001';
|
||||
@fa-var-navicon: '\f0c9';
|
||||
@fa-var-neuter: '\f22c';
|
||||
@fa-var-newspaper-o: '\f1ea';
|
||||
@fa-var-object-group: '\f247';
|
||||
@fa-var-object-ungroup: '\f248';
|
||||
@fa-var-odnoklassniki: '\f263';
|
||||
@fa-var-odnoklassniki-square: '\f264';
|
||||
@fa-var-opencart: '\f23d';
|
||||
@fa-var-openid: '\f19b';
|
||||
@fa-var-opera: '\f26a';
|
||||
@fa-var-optin-monster: '\f23c';
|
||||
@fa-var-outdent: '\f03b';
|
||||
@fa-var-pagelines: '\f18c';
|
||||
@fa-var-paint-brush: '\f1fc';
|
||||
@fa-var-paper-plane: '\f1d8';
|
||||
@fa-var-paper-plane-o: '\f1d9';
|
||||
@fa-var-paperclip: '\f0c6';
|
||||
@fa-var-paragraph: '\f1dd';
|
||||
@fa-var-paste: '\f0ea';
|
||||
@fa-var-pause: '\f04c';
|
||||
@fa-var-pause-circle: '\f28b';
|
||||
@fa-var-pause-circle-o: '\f28c';
|
||||
@fa-var-paw: '\f1b0';
|
||||
@fa-var-paypal: '\f1ed';
|
||||
@fa-var-pencil: '\f040';
|
||||
@fa-var-pencil-square: '\f14b';
|
||||
@fa-var-pencil-square-o: '\f044';
|
||||
@fa-var-percent: '\f295';
|
||||
@fa-var-phone: '\f095';
|
||||
@fa-var-phone-square: '\f098';
|
||||
@fa-var-photo: '\f03e';
|
||||
@fa-var-picture-o: '\f03e';
|
||||
@fa-var-pie-chart: '\f200';
|
||||
@fa-var-pied-piper: '\f2ae';
|
||||
@fa-var-pied-piper-alt: '\f1a8';
|
||||
@fa-var-pied-piper-pp: '\f1a7';
|
||||
@fa-var-pinterest: '\f0d2';
|
||||
@fa-var-pinterest-p: '\f231';
|
||||
@fa-var-pinterest-square: '\f0d3';
|
||||
@fa-var-plane: '\f072';
|
||||
@fa-var-play: '\f04b';
|
||||
@fa-var-play-circle: '\f144';
|
||||
@fa-var-play-circle-o: '\f01d';
|
||||
@fa-var-plug: '\f1e6';
|
||||
@fa-var-plus: '\f067';
|
||||
@fa-var-plus-circle: '\f055';
|
||||
@fa-var-plus-square: '\f0fe';
|
||||
@fa-var-plus-square-o: '\f196';
|
||||
@fa-var-podcast: '\f2ce';
|
||||
@fa-var-power-off: '\f011';
|
||||
@fa-var-print: '\f02f';
|
||||
@fa-var-product-hunt: '\f288';
|
||||
@fa-var-puzzle-piece: '\f12e';
|
||||
@fa-var-qq: '\f1d6';
|
||||
@fa-var-qrcode: '\f029';
|
||||
@fa-var-question: '\f128';
|
||||
@fa-var-question-circle: '\f059';
|
||||
@fa-var-question-circle-o: '\f29c';
|
||||
@fa-var-quora: '\f2c4';
|
||||
@fa-var-quote-left: '\f10d';
|
||||
@fa-var-quote-right: '\f10e';
|
||||
@fa-var-ra: '\f1d0';
|
||||
@fa-var-random: '\f074';
|
||||
@fa-var-ravelry: '\f2d9';
|
||||
@fa-var-rebel: '\f1d0';
|
||||
@fa-var-recycle: '\f1b8';
|
||||
@fa-var-reddit: '\f1a1';
|
||||
@fa-var-reddit-alien: '\f281';
|
||||
@fa-var-reddit-square: '\f1a2';
|
||||
@fa-var-refresh: '\f021';
|
||||
@fa-var-registered: '\f25d';
|
||||
@fa-var-remove: '\f00d';
|
||||
@fa-var-renren: '\f18b';
|
||||
@fa-var-reorder: '\f0c9';
|
||||
@fa-var-repeat: '\f01e';
|
||||
@fa-var-reply: '\f112';
|
||||
@fa-var-reply-all: '\f122';
|
||||
@fa-var-resistance: '\f1d0';
|
||||
@fa-var-retweet: '\f079';
|
||||
@fa-var-rmb: '\f157';
|
||||
@fa-var-road: '\f018';
|
||||
@fa-var-rocket: '\f135';
|
||||
@fa-var-rotate-left: '\f0e2';
|
||||
@fa-var-rotate-right: '\f01e';
|
||||
@fa-var-rouble: '\f158';
|
||||
@fa-var-rss: '\f09e';
|
||||
@fa-var-rss-square: '\f143';
|
||||
@fa-var-rub: '\f158';
|
||||
@fa-var-ruble: '\f158';
|
||||
@fa-var-rupee: '\f156';
|
||||
@fa-var-s15: '\f2cd';
|
||||
@fa-var-safari: '\f267';
|
||||
@fa-var-save: '\f0c7';
|
||||
@fa-var-scissors: '\f0c4';
|
||||
@fa-var-scribd: '\f28a';
|
||||
@fa-var-search: '\f002';
|
||||
@fa-var-search-minus: '\f010';
|
||||
@fa-var-search-plus: '\f00e';
|
||||
@fa-var-sellsy: '\f213';
|
||||
@fa-var-send: '\f1d8';
|
||||
@fa-var-send-o: '\f1d9';
|
||||
@fa-var-server: '\f233';
|
||||
@fa-var-share: '\f064';
|
||||
@fa-var-share-alt: '\f1e0';
|
||||
@fa-var-share-alt-square: '\f1e1';
|
||||
@fa-var-share-square: '\f14d';
|
||||
@fa-var-share-square-o: '\f045';
|
||||
@fa-var-shekel: '\f20b';
|
||||
@fa-var-sheqel: '\f20b';
|
||||
@fa-var-shield: '\f132';
|
||||
@fa-var-ship: '\f21a';
|
||||
@fa-var-shirtsinbulk: '\f214';
|
||||
@fa-var-shopping-bag: '\f290';
|
||||
@fa-var-shopping-basket: '\f291';
|
||||
@fa-var-shopping-cart: '\f07a';
|
||||
@fa-var-shower: '\f2cc';
|
||||
@fa-var-sign-in: '\f090';
|
||||
@fa-var-sign-language: '\f2a7';
|
||||
@fa-var-sign-out: '\f08b';
|
||||
@fa-var-signal: '\f012';
|
||||
@fa-var-signing: '\f2a7';
|
||||
@fa-var-simplybuilt: '\f215';
|
||||
@fa-var-sitemap: '\f0e8';
|
||||
@fa-var-skyatlas: '\f216';
|
||||
@fa-var-skype: '\f17e';
|
||||
@fa-var-slack: '\f198';
|
||||
@fa-var-sliders: '\f1de';
|
||||
@fa-var-slideshare: '\f1e7';
|
||||
@fa-var-smile-o: '\f118';
|
||||
@fa-var-snapchat: '\f2ab';
|
||||
@fa-var-snapchat-ghost: '\f2ac';
|
||||
@fa-var-snapchat-square: '\f2ad';
|
||||
@fa-var-snowflake-o: '\f2dc';
|
||||
@fa-var-soccer-ball-o: '\f1e3';
|
||||
@fa-var-sort: '\f0dc';
|
||||
@fa-var-sort-alpha-asc: '\f15d';
|
||||
@fa-var-sort-alpha-desc: '\f15e';
|
||||
@fa-var-sort-amount-asc: '\f160';
|
||||
@fa-var-sort-amount-desc: '\f161';
|
||||
@fa-var-sort-asc: '\f0de';
|
||||
@fa-var-sort-desc: '\f0dd';
|
||||
@fa-var-sort-down: '\f0dd';
|
||||
@fa-var-sort-numeric-asc: '\f162';
|
||||
@fa-var-sort-numeric-desc: '\f163';
|
||||
@fa-var-sort-up: '\f0de';
|
||||
@fa-var-soundcloud: '\f1be';
|
||||
@fa-var-space-shuttle: '\f197';
|
||||
@fa-var-spinner: '\f110';
|
||||
@fa-var-spoon: '\f1b1';
|
||||
@fa-var-spotify: '\f1bc';
|
||||
@fa-var-square: '\f0c8';
|
||||
@fa-var-square-o: '\f096';
|
||||
@fa-var-stack-exchange: '\f18d';
|
||||
@fa-var-stack-overflow: '\f16c';
|
||||
@fa-var-star: '\f005';
|
||||
@fa-var-star-half: '\f089';
|
||||
@fa-var-star-half-empty: '\f123';
|
||||
@fa-var-star-half-full: '\f123';
|
||||
@fa-var-star-half-o: '\f123';
|
||||
@fa-var-star-o: '\f006';
|
||||
@fa-var-steam: '\f1b6';
|
||||
@fa-var-steam-square: '\f1b7';
|
||||
@fa-var-step-backward: '\f048';
|
||||
@fa-var-step-forward: '\f051';
|
||||
@fa-var-stethoscope: '\f0f1';
|
||||
@fa-var-sticky-note: '\f249';
|
||||
@fa-var-sticky-note-o: '\f24a';
|
||||
@fa-var-stop: '\f04d';
|
||||
@fa-var-stop-circle: '\f28d';
|
||||
@fa-var-stop-circle-o: '\f28e';
|
||||
@fa-var-street-view: '\f21d';
|
||||
@fa-var-strikethrough: '\f0cc';
|
||||
@fa-var-stumbleupon: '\f1a4';
|
||||
@fa-var-stumbleupon-circle: '\f1a3';
|
||||
@fa-var-subscript: '\f12c';
|
||||
@fa-var-subway: '\f239';
|
||||
@fa-var-suitcase: '\f0f2';
|
||||
@fa-var-sun-o: '\f185';
|
||||
@fa-var-superpowers: '\f2dd';
|
||||
@fa-var-superscript: '\f12b';
|
||||
@fa-var-support: '\f1cd';
|
||||
@fa-var-table: '\f0ce';
|
||||
@fa-var-tablet: '\f10a';
|
||||
@fa-var-tachometer: '\f0e4';
|
||||
@fa-var-tag: '\f02b';
|
||||
@fa-var-tags: '\f02c';
|
||||
@fa-var-tasks: '\f0ae';
|
||||
@fa-var-taxi: '\f1ba';
|
||||
@fa-var-telegram: '\f2c6';
|
||||
@fa-var-television: '\f26c';
|
||||
@fa-var-tencent-weibo: '\f1d5';
|
||||
@fa-var-terminal: '\f120';
|
||||
@fa-var-text-height: '\f034';
|
||||
@fa-var-text-width: '\f035';
|
||||
@fa-var-th: '\f00a';
|
||||
@fa-var-th-large: '\f009';
|
||||
@fa-var-th-list: '\f00b';
|
||||
@fa-var-themeisle: '\f2b2';
|
||||
@fa-var-thermometer: '\f2c7';
|
||||
@fa-var-thermometer-0: '\f2cb';
|
||||
@fa-var-thermometer-1: '\f2ca';
|
||||
@fa-var-thermometer-2: '\f2c9';
|
||||
@fa-var-thermometer-3: '\f2c8';
|
||||
@fa-var-thermometer-4: '\f2c7';
|
||||
@fa-var-thermometer-empty: '\f2cb';
|
||||
@fa-var-thermometer-full: '\f2c7';
|
||||
@fa-var-thermometer-half: '\f2c9';
|
||||
@fa-var-thermometer-quarter: '\f2ca';
|
||||
@fa-var-thermometer-three-quarters: '\f2c8';
|
||||
@fa-var-thumb-tack: '\f08d';
|
||||
@fa-var-thumbs-down: '\f165';
|
||||
@fa-var-thumbs-o-down: '\f088';
|
||||
@fa-var-thumbs-o-up: '\f087';
|
||||
@fa-var-thumbs-up: '\f164';
|
||||
@fa-var-ticket: '\f145';
|
||||
@fa-var-times: '\f00d';
|
||||
@fa-var-times-circle: '\f057';
|
||||
@fa-var-times-circle-o: '\f05c';
|
||||
@fa-var-times-rectangle: '\f2d3';
|
||||
@fa-var-times-rectangle-o: '\f2d4';
|
||||
@fa-var-tint: '\f043';
|
||||
@fa-var-toggle-down: '\f150';
|
||||
@fa-var-toggle-left: '\f191';
|
||||
@fa-var-toggle-off: '\f204';
|
||||
@fa-var-toggle-on: '\f205';
|
||||
@fa-var-toggle-right: '\f152';
|
||||
@fa-var-toggle-up: '\f151';
|
||||
@fa-var-trademark: '\f25c';
|
||||
@fa-var-train: '\f238';
|
||||
@fa-var-transgender: '\f224';
|
||||
@fa-var-transgender-alt: '\f225';
|
||||
@fa-var-trash: '\f1f8';
|
||||
@fa-var-trash-o: '\f014';
|
||||
@fa-var-tree: '\f1bb';
|
||||
@fa-var-trello: '\f181';
|
||||
@fa-var-tripadvisor: '\f262';
|
||||
@fa-var-trophy: '\f091';
|
||||
@fa-var-truck: '\f0d1';
|
||||
@fa-var-try: '\f195';
|
||||
@fa-var-tty: '\f1e4';
|
||||
@fa-var-tumblr: '\f173';
|
||||
@fa-var-tumblr-square: '\f174';
|
||||
@fa-var-turkish-lira: '\f195';
|
||||
@fa-var-tv: '\f26c';
|
||||
@fa-var-twitch: '\f1e8';
|
||||
@fa-var-twitter: '\f099';
|
||||
@fa-var-twitter-square: '\f081';
|
||||
@fa-var-umbrella: '\f0e9';
|
||||
@fa-var-underline: '\f0cd';
|
||||
@fa-var-undo: '\f0e2';
|
||||
@fa-var-universal-access: '\f29a';
|
||||
@fa-var-university: '\f19c';
|
||||
@fa-var-unlink: '\f127';
|
||||
@fa-var-unlock: '\f09c';
|
||||
@fa-var-unlock-alt: '\f13e';
|
||||
@fa-var-unsorted: '\f0dc';
|
||||
@fa-var-upload: '\f093';
|
||||
@fa-var-usb: '\f287';
|
||||
@fa-var-usd: '\f155';
|
||||
@fa-var-user: '\f007';
|
||||
@fa-var-user-circle: '\f2bd';
|
||||
@fa-var-user-circle-o: '\f2be';
|
||||
@fa-var-user-md: '\f0f0';
|
||||
@fa-var-user-o: '\f2c0';
|
||||
@fa-var-user-plus: '\f234';
|
||||
@fa-var-user-secret: '\f21b';
|
||||
@fa-var-user-times: '\f235';
|
||||
@fa-var-users: '\f0c0';
|
||||
@fa-var-vcard: '\f2bb';
|
||||
@fa-var-vcard-o: '\f2bc';
|
||||
@fa-var-venus: '\f221';
|
||||
@fa-var-venus-double: '\f226';
|
||||
@fa-var-venus-mars: '\f228';
|
||||
@fa-var-viacoin: '\f237';
|
||||
@fa-var-viadeo: '\f2a9';
|
||||
@fa-var-viadeo-square: '\f2aa';
|
||||
@fa-var-video-camera: '\f03d';
|
||||
@fa-var-vimeo: '\f27d';
|
||||
@fa-var-vimeo-square: '\f194';
|
||||
@fa-var-vine: '\f1ca';
|
||||
@fa-var-vk: '\f189';
|
||||
@fa-var-volume-control-phone: '\f2a0';
|
||||
@fa-var-volume-down: '\f027';
|
||||
@fa-var-volume-off: '\f026';
|
||||
@fa-var-volume-up: '\f028';
|
||||
@fa-var-warning: '\f071';
|
||||
@fa-var-wechat: '\f1d7';
|
||||
@fa-var-weibo: '\f18a';
|
||||
@fa-var-weixin: '\f1d7';
|
||||
@fa-var-whatsapp: '\f232';
|
||||
@fa-var-wheelchair: '\f193';
|
||||
@fa-var-wheelchair-alt: '\f29b';
|
||||
@fa-var-wifi: '\f1eb';
|
||||
@fa-var-wikipedia-w: '\f266';
|
||||
@fa-var-window-close: '\f2d3';
|
||||
@fa-var-window-close-o: '\f2d4';
|
||||
@fa-var-window-maximize: '\f2d0';
|
||||
@fa-var-window-minimize: '\f2d1';
|
||||
@fa-var-window-restore: '\f2d2';
|
||||
@fa-var-windows: '\f17a';
|
||||
@fa-var-won: '\f159';
|
||||
@fa-var-wordpress: '\f19a';
|
||||
@fa-var-wpbeginner: '\f297';
|
||||
@fa-var-wpexplorer: '\f2de';
|
||||
@fa-var-wpforms: '\f298';
|
||||
@fa-var-wrench: '\f0ad';
|
||||
@fa-var-xing: '\f168';
|
||||
@fa-var-xing-square: '\f169';
|
||||
@fa-var-y-combinator: '\f23b';
|
||||
@fa-var-y-combinator-square: '\f1d4';
|
||||
@fa-var-yahoo: '\f19e';
|
||||
@fa-var-yc: '\f23b';
|
||||
@fa-var-yc-square: '\f1d4';
|
||||
@fa-var-yelp: '\f1e9';
|
||||
@fa-var-yen: '\f157';
|
||||
@fa-var-yoast: '\f2b1';
|
||||
@fa-var-youtube: '\f167';
|
||||
@fa-var-youtube-play: '\f16a';
|
||||
@fa-var-youtube-square: '\f166';
|
34
public/font-awesome-4.7.0/scss/_animated.scss
Normal file
34
public/font-awesome-4.7.0/scss/_animated.scss
Normal file
@ -0,0 +1,34 @@
|
||||
// Spinning Icons
|
||||
// --------------------------
|
||||
|
||||
.#{$fa-css-prefix}-spin {
|
||||
-webkit-animation: fa-spin 2s infinite linear;
|
||||
animation: fa-spin 2s infinite linear;
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix}-pulse {
|
||||
-webkit-animation: fa-spin 1s infinite steps(8);
|
||||
animation: fa-spin 1s infinite steps(8);
|
||||
}
|
||||
|
||||
@-webkit-keyframes fa-spin {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: rotate(359deg);
|
||||
transform: rotate(359deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fa-spin {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: rotate(359deg);
|
||||
transform: rotate(359deg);
|
||||
}
|
||||
}
|
41
public/font-awesome-4.7.0/scss/_bordered-pulled.scss
Normal file
41
public/font-awesome-4.7.0/scss/_bordered-pulled.scss
Normal file
@ -0,0 +1,41 @@
|
||||
// Bordered & Pulled
|
||||
// -------------------------
|
||||
|
||||
.#{$fa-css-prefix}-border {
|
||||
padding: 0.2em 0.25em 0.15em;
|
||||
border: solid 0.08em $fa-border-color;
|
||||
border-radius: 0.1em;
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix}-pull-left {
|
||||
float: left;
|
||||
}
|
||||
.#{$fa-css-prefix}-pull-right {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix} {
|
||||
&.#{$fa-css-prefix}-pull-left {
|
||||
margin-right: 0.3em;
|
||||
}
|
||||
&.#{$fa-css-prefix}-pull-right {
|
||||
margin-left: 0.3em;
|
||||
}
|
||||
}
|
||||
|
||||
/* Deprecated as of 4.4.0 */
|
||||
.pull-right {
|
||||
float: right;
|
||||
}
|
||||
.pull-left {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix} {
|
||||
&.pull-left {
|
||||
margin-right: 0.3em;
|
||||
}
|
||||
&.pull-right {
|
||||
margin-left: 0.3em;
|
||||
}
|
||||
}
|
11
public/font-awesome-4.7.0/scss/_core.scss
Normal file
11
public/font-awesome-4.7.0/scss/_core.scss
Normal file
@ -0,0 +1,11 @@
|
||||
// Base Class Definition
|
||||
// -------------------------
|
||||
|
||||
.#{$fa-css-prefix} {
|
||||
display: inline-block;
|
||||
font: normal normal normal #{$fa-font-size-base}/#{$fa-line-height-base} FontAwesome; // shortening font declaration
|
||||
font-size: inherit; // can't have font-size inherit on line above, so need to override
|
||||
text-rendering: auto; // optimizelegibility throws things off #1094
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
6
public/font-awesome-4.7.0/scss/_fixed-width.scss
Normal file
6
public/font-awesome-4.7.0/scss/_fixed-width.scss
Normal file
@ -0,0 +1,6 @@
|
||||
// Fixed Width Icons
|
||||
// -------------------------
|
||||
.#{$fa-css-prefix}-fw {
|
||||
width: (18em / 14);
|
||||
text-align: center;
|
||||
}
|
2139
public/font-awesome-4.7.0/scss/_icons.scss
Normal file
2139
public/font-awesome-4.7.0/scss/_icons.scss
Normal file
File diff suppressed because it is too large
Load Diff
21
public/font-awesome-4.7.0/scss/_larger.scss
Normal file
21
public/font-awesome-4.7.0/scss/_larger.scss
Normal file
@ -0,0 +1,21 @@
|
||||
// Icon Sizes
|
||||
// -------------------------
|
||||
|
||||
/* makes the font 33% larger relative to the icon container */
|
||||
.#{$fa-css-prefix}-lg {
|
||||
font-size: (4em / 3);
|
||||
line-height: (3em / 4);
|
||||
vertical-align: -15%;
|
||||
}
|
||||
.#{$fa-css-prefix}-2x {
|
||||
font-size: 2em;
|
||||
}
|
||||
.#{$fa-css-prefix}-3x {
|
||||
font-size: 3em;
|
||||
}
|
||||
.#{$fa-css-prefix}-4x {
|
||||
font-size: 4em;
|
||||
}
|
||||
.#{$fa-css-prefix}-5x {
|
||||
font-size: 5em;
|
||||
}
|
21
public/font-awesome-4.7.0/scss/_list.scss
Normal file
21
public/font-awesome-4.7.0/scss/_list.scss
Normal file
@ -0,0 +1,21 @@
|
||||
// List Icons
|
||||
// -------------------------
|
||||
|
||||
.#{$fa-css-prefix}-ul {
|
||||
padding-left: 0;
|
||||
margin-left: $fa-li-width;
|
||||
list-style-type: none;
|
||||
> li {
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
.#{$fa-css-prefix}-li {
|
||||
position: absolute;
|
||||
left: -$fa-li-width;
|
||||
width: $fa-li-width;
|
||||
top: (2em / 14);
|
||||
text-align: center;
|
||||
&.#{$fa-css-prefix}-lg {
|
||||
left: -$fa-li-width + (4em / 14);
|
||||
}
|
||||
}
|
58
public/font-awesome-4.7.0/scss/_mixins.scss
Normal file
58
public/font-awesome-4.7.0/scss/_mixins.scss
Normal file
@ -0,0 +1,58 @@
|
||||
// Mixins
|
||||
// --------------------------
|
||||
|
||||
@mixin fa-icon() {
|
||||
display: inline-block;
|
||||
font: normal normal normal #{$fa-font-size-base}/#{$fa-line-height-base} FontAwesome; // shortening font declaration
|
||||
font-size: inherit; // can't have font-size inherit on line above, so need to override
|
||||
text-rendering: auto; // optimizelegibility throws things off #1094
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
@mixin fa-icon-rotate($degrees, $rotation) {
|
||||
-ms-filter: 'progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation})';
|
||||
-webkit-transform: rotate($degrees);
|
||||
-ms-transform: rotate($degrees);
|
||||
transform: rotate($degrees);
|
||||
}
|
||||
|
||||
@mixin fa-icon-flip($horiz, $vert, $rotation) {
|
||||
-ms-filter: 'progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation}, mirror=1)';
|
||||
-webkit-transform: scale($horiz, $vert);
|
||||
-ms-transform: scale($horiz, $vert);
|
||||
transform: scale($horiz, $vert);
|
||||
}
|
||||
|
||||
// Only display content to screen readers. A la Bootstrap 4.
|
||||
//
|
||||
// See: http://a11yproject.com/posts/how-to-hide-content/
|
||||
|
||||
@mixin sr-only {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
border: 0;
|
||||
}
|
||||
|
||||
// Use in conjunction with .sr-only to only display content when it's focused.
|
||||
//
|
||||
// Useful for "Skip to main content" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1
|
||||
//
|
||||
// Credit: HTML5 Boilerplate
|
||||
|
||||
@mixin sr-only-focusable {
|
||||
&:active,
|
||||
&:focus {
|
||||
position: static;
|
||||
width: auto;
|
||||
height: auto;
|
||||
margin: 0;
|
||||
overflow: visible;
|
||||
clip: auto;
|
||||
}
|
||||
}
|
17
public/font-awesome-4.7.0/scss/_path.scss
Normal file
17
public/font-awesome-4.7.0/scss/_path.scss
Normal file
@ -0,0 +1,17 @@
|
||||
/* FONT PATH
|
||||
* -------------------------- */
|
||||
|
||||
@font-face {
|
||||
font-family: 'FontAwesome';
|
||||
src: url('#{$fa-font-path}/fontawesome-webfont.eot?v=#{$fa-version}');
|
||||
src: url('#{$fa-font-path}/fontawesome-webfont.eot?#iefix&v=#{$fa-version}')
|
||||
format('embedded-opentype'),
|
||||
url('#{$fa-font-path}/fontawesome-webfont.woff2?v=#{$fa-version}') format('woff2'),
|
||||
url('#{$fa-font-path}/fontawesome-webfont.woff?v=#{$fa-version}') format('woff'),
|
||||
url('#{$fa-font-path}/fontawesome-webfont.ttf?v=#{$fa-version}') format('truetype'),
|
||||
url('#{$fa-font-path}/fontawesome-webfont.svg?v=#{$fa-version}#fontawesomeregular')
|
||||
format('svg');
|
||||
// src: url('#{$fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
30
public/font-awesome-4.7.0/scss/_rotated-flipped.scss
Normal file
30
public/font-awesome-4.7.0/scss/_rotated-flipped.scss
Normal file
@ -0,0 +1,30 @@
|
||||
// Rotated & Flipped Icons
|
||||
// -------------------------
|
||||
|
||||
.#{$fa-css-prefix}-rotate-90 {
|
||||
@include fa-icon-rotate(90deg, 1);
|
||||
}
|
||||
.#{$fa-css-prefix}-rotate-180 {
|
||||
@include fa-icon-rotate(180deg, 2);
|
||||
}
|
||||
.#{$fa-css-prefix}-rotate-270 {
|
||||
@include fa-icon-rotate(270deg, 3);
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix}-flip-horizontal {
|
||||
@include fa-icon-flip(-1, 1, 0);
|
||||
}
|
||||
.#{$fa-css-prefix}-flip-vertical {
|
||||
@include fa-icon-flip(1, -1, 2);
|
||||
}
|
||||
|
||||
// Hook for IE8-9
|
||||
// -------------------------
|
||||
|
||||
:root .#{$fa-css-prefix}-rotate-90,
|
||||
:root .#{$fa-css-prefix}-rotate-180,
|
||||
:root .#{$fa-css-prefix}-rotate-270,
|
||||
:root .#{$fa-css-prefix}-flip-horizontal,
|
||||
:root .#{$fa-css-prefix}-flip-vertical {
|
||||
filter: none;
|
||||
}
|
9
public/font-awesome-4.7.0/scss/_screen-reader.scss
Normal file
9
public/font-awesome-4.7.0/scss/_screen-reader.scss
Normal file
@ -0,0 +1,9 @@
|
||||
// Screen Readers
|
||||
// -------------------------
|
||||
|
||||
.sr-only {
|
||||
@include sr-only();
|
||||
}
|
||||
.sr-only-focusable {
|
||||
@include sr-only-focusable();
|
||||
}
|
27
public/font-awesome-4.7.0/scss/_stacked.scss
Normal file
27
public/font-awesome-4.7.0/scss/_stacked.scss
Normal file
@ -0,0 +1,27 @@
|
||||
// Stacked Icons
|
||||
// -------------------------
|
||||
|
||||
.#{$fa-css-prefix}-stack {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 2em;
|
||||
height: 2em;
|
||||
line-height: 2em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.#{$fa-css-prefix}-stack-1x,
|
||||
.#{$fa-css-prefix}-stack-2x {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
.#{$fa-css-prefix}-stack-1x {
|
||||
line-height: inherit;
|
||||
}
|
||||
.#{$fa-css-prefix}-stack-2x {
|
||||
font-size: 2em;
|
||||
}
|
||||
.#{$fa-css-prefix}-inverse {
|
||||
color: $fa-inverse;
|
||||
}
|
799
public/font-awesome-4.7.0/scss/_variables.scss
Normal file
799
public/font-awesome-4.7.0/scss/_variables.scss
Normal file
@ -0,0 +1,799 @@
|
||||
// Variables
|
||||
// --------------------------
|
||||
|
||||
$fa-font-path: '../fonts' !default;
|
||||
$fa-font-size-base: 14px !default;
|
||||
$fa-line-height-base: 1 !default;
|
||||
//$fa-font-path: "//netdna.bootstrapcdn.com/font-awesome/4.7.0/fonts" !default; // for referencing Bootstrap CDN font files directly
|
||||
$fa-css-prefix: fa !default;
|
||||
$fa-version: '4.7.0' !default;
|
||||
$fa-border-color: #eee !default;
|
||||
$fa-inverse: #fff !default;
|
||||
$fa-li-width: (30em / 14) !default;
|
||||
|
||||
$fa-var-500px: '\f26e';
|
||||
$fa-var-address-book: '\f2b9';
|
||||
$fa-var-address-book-o: '\f2ba';
|
||||
$fa-var-address-card: '\f2bb';
|
||||
$fa-var-address-card-o: '\f2bc';
|
||||
$fa-var-adjust: '\f042';
|
||||
$fa-var-adn: '\f170';
|
||||
$fa-var-align-center: '\f037';
|
||||
$fa-var-align-justify: '\f039';
|
||||
$fa-var-align-left: '\f036';
|
||||
$fa-var-align-right: '\f038';
|
||||
$fa-var-amazon: '\f270';
|
||||
$fa-var-ambulance: '\f0f9';
|
||||
$fa-var-american-sign-language-interpreting: '\f2a3';
|
||||
$fa-var-anchor: '\f13d';
|
||||
$fa-var-android: '\f17b';
|
||||
$fa-var-angellist: '\f209';
|
||||
$fa-var-angle-double-down: '\f103';
|
||||
$fa-var-angle-double-left: '\f100';
|
||||
$fa-var-angle-double-right: '\f101';
|
||||
$fa-var-angle-double-up: '\f102';
|
||||
$fa-var-angle-down: '\f107';
|
||||
$fa-var-angle-left: '\f104';
|
||||
$fa-var-angle-right: '\f105';
|
||||
$fa-var-angle-up: '\f106';
|
||||
$fa-var-apple: '\f179';
|
||||
$fa-var-archive: '\f187';
|
||||
$fa-var-area-chart: '\f1fe';
|
||||
$fa-var-arrow-circle-down: '\f0ab';
|
||||
$fa-var-arrow-circle-left: '\f0a8';
|
||||
$fa-var-arrow-circle-o-down: '\f01a';
|
||||
$fa-var-arrow-circle-o-left: '\f190';
|
||||
$fa-var-arrow-circle-o-right: '\f18e';
|
||||
$fa-var-arrow-circle-o-up: '\f01b';
|
||||
$fa-var-arrow-circle-right: '\f0a9';
|
||||
$fa-var-arrow-circle-up: '\f0aa';
|
||||
$fa-var-arrow-down: '\f063';
|
||||
$fa-var-arrow-left: '\f060';
|
||||
$fa-var-arrow-right: '\f061';
|
||||
$fa-var-arrow-up: '\f062';
|
||||
$fa-var-arrows: '\f047';
|
||||
$fa-var-arrows-alt: '\f0b2';
|
||||
$fa-var-arrows-h: '\f07e';
|
||||
$fa-var-arrows-v: '\f07d';
|
||||
$fa-var-asl-interpreting: '\f2a3';
|
||||
$fa-var-assistive-listening-systems: '\f2a2';
|
||||
$fa-var-asterisk: '\f069';
|
||||
$fa-var-at: '\f1fa';
|
||||
$fa-var-audio-description: '\f29e';
|
||||
$fa-var-automobile: '\f1b9';
|
||||
$fa-var-backward: '\f04a';
|
||||
$fa-var-balance-scale: '\f24e';
|
||||
$fa-var-ban: '\f05e';
|
||||
$fa-var-bandcamp: '\f2d5';
|
||||
$fa-var-bank: '\f19c';
|
||||
$fa-var-bar-chart: '\f080';
|
||||
$fa-var-bar-chart-o: '\f080';
|
||||
$fa-var-barcode: '\f02a';
|
||||
$fa-var-bars: '\f0c9';
|
||||
$fa-var-bath: '\f2cd';
|
||||
$fa-var-bathtub: '\f2cd';
|
||||
$fa-var-battery: '\f240';
|
||||
$fa-var-battery-0: '\f244';
|
||||
$fa-var-battery-1: '\f243';
|
||||
$fa-var-battery-2: '\f242';
|
||||
$fa-var-battery-3: '\f241';
|
||||
$fa-var-battery-4: '\f240';
|
||||
$fa-var-battery-empty: '\f244';
|
||||
$fa-var-battery-full: '\f240';
|
||||
$fa-var-battery-half: '\f242';
|
||||
$fa-var-battery-quarter: '\f243';
|
||||
$fa-var-battery-three-quarters: '\f241';
|
||||
$fa-var-bed: '\f236';
|
||||
$fa-var-beer: '\f0fc';
|
||||
$fa-var-behance: '\f1b4';
|
||||
$fa-var-behance-square: '\f1b5';
|
||||
$fa-var-bell: '\f0f3';
|
||||
$fa-var-bell-o: '\f0a2';
|
||||
$fa-var-bell-slash: '\f1f6';
|
||||
$fa-var-bell-slash-o: '\f1f7';
|
||||
$fa-var-bicycle: '\f206';
|
||||
$fa-var-binoculars: '\f1e5';
|
||||
$fa-var-birthday-cake: '\f1fd';
|
||||
$fa-var-bitbucket: '\f171';
|
||||
$fa-var-bitbucket-square: '\f172';
|
||||
$fa-var-bitcoin: '\f15a';
|
||||
$fa-var-black-tie: '\f27e';
|
||||
$fa-var-blind: '\f29d';
|
||||
$fa-var-bluetooth: '\f293';
|
||||
$fa-var-bluetooth-b: '\f294';
|
||||
$fa-var-bold: '\f032';
|
||||
$fa-var-bolt: '\f0e7';
|
||||
$fa-var-bomb: '\f1e2';
|
||||
$fa-var-book: '\f02d';
|
||||
$fa-var-bookmark: '\f02e';
|
||||
$fa-var-bookmark-o: '\f097';
|
||||
$fa-var-braille: '\f2a1';
|
||||
$fa-var-briefcase: '\f0b1';
|
||||
$fa-var-btc: '\f15a';
|
||||
$fa-var-bug: '\f188';
|
||||
$fa-var-building: '\f1ad';
|
||||
$fa-var-building-o: '\f0f7';
|
||||
$fa-var-bullhorn: '\f0a1';
|
||||
$fa-var-bullseye: '\f140';
|
||||
$fa-var-bus: '\f207';
|
||||
$fa-var-buysellads: '\f20d';
|
||||
$fa-var-cab: '\f1ba';
|
||||
$fa-var-calculator: '\f1ec';
|
||||
$fa-var-calendar: '\f073';
|
||||
$fa-var-calendar-check-o: '\f274';
|
||||
$fa-var-calendar-minus-o: '\f272';
|
||||
$fa-var-calendar-o: '\f133';
|
||||
$fa-var-calendar-plus-o: '\f271';
|
||||
$fa-var-calendar-times-o: '\f273';
|
||||
$fa-var-camera: '\f030';
|
||||
$fa-var-camera-retro: '\f083';
|
||||
$fa-var-car: '\f1b9';
|
||||
$fa-var-caret-down: '\f0d7';
|
||||
$fa-var-caret-left: '\f0d9';
|
||||
$fa-var-caret-right: '\f0da';
|
||||
$fa-var-caret-square-o-down: '\f150';
|
||||
$fa-var-caret-square-o-left: '\f191';
|
||||
$fa-var-caret-square-o-right: '\f152';
|
||||
$fa-var-caret-square-o-up: '\f151';
|
||||
$fa-var-caret-up: '\f0d8';
|
||||
$fa-var-cart-arrow-down: '\f218';
|
||||
$fa-var-cart-plus: '\f217';
|
||||
$fa-var-cc: '\f20a';
|
||||
$fa-var-cc-amex: '\f1f3';
|
||||
$fa-var-cc-diners-club: '\f24c';
|
||||
$fa-var-cc-discover: '\f1f2';
|
||||
$fa-var-cc-jcb: '\f24b';
|
||||
$fa-var-cc-mastercard: '\f1f1';
|
||||
$fa-var-cc-paypal: '\f1f4';
|
||||
$fa-var-cc-stripe: '\f1f5';
|
||||
$fa-var-cc-visa: '\f1f0';
|
||||
$fa-var-certificate: '\f0a3';
|
||||
$fa-var-chain: '\f0c1';
|
||||
$fa-var-chain-broken: '\f127';
|
||||
$fa-var-check: '\f00c';
|
||||
$fa-var-check-circle: '\f058';
|
||||
$fa-var-check-circle-o: '\f05d';
|
||||
$fa-var-check-square: '\f14a';
|
||||
$fa-var-check-square-o: '\f046';
|
||||
$fa-var-chevron-circle-down: '\f13a';
|
||||
$fa-var-chevron-circle-left: '\f137';
|
||||
$fa-var-chevron-circle-right: '\f138';
|
||||
$fa-var-chevron-circle-up: '\f139';
|
||||
$fa-var-chevron-down: '\f078';
|
||||
$fa-var-chevron-left: '\f053';
|
||||
$fa-var-chevron-right: '\f054';
|
||||
$fa-var-chevron-up: '\f077';
|
||||
$fa-var-child: '\f1ae';
|
||||
$fa-var-chrome: '\f268';
|
||||
$fa-var-circle: '\f111';
|
||||
$fa-var-circle-o: '\f10c';
|
||||
$fa-var-circle-o-notch: '\f1ce';
|
||||
$fa-var-circle-thin: '\f1db';
|
||||
$fa-var-clipboard: '\f0ea';
|
||||
$fa-var-clock-o: '\f017';
|
||||
$fa-var-clone: '\f24d';
|
||||
$fa-var-close: '\f00d';
|
||||
$fa-var-cloud: '\f0c2';
|
||||
$fa-var-cloud-download: '\f0ed';
|
||||
$fa-var-cloud-upload: '\f0ee';
|
||||
$fa-var-cny: '\f157';
|
||||
$fa-var-code: '\f121';
|
||||
$fa-var-code-fork: '\f126';
|
||||
$fa-var-codepen: '\f1cb';
|
||||
$fa-var-codiepie: '\f284';
|
||||
$fa-var-coffee: '\f0f4';
|
||||
$fa-var-cog: '\f013';
|
||||
$fa-var-cogs: '\f085';
|
||||
$fa-var-columns: '\f0db';
|
||||
$fa-var-comment: '\f075';
|
||||
$fa-var-comment-o: '\f0e5';
|
||||
$fa-var-commenting: '\f27a';
|
||||
$fa-var-commenting-o: '\f27b';
|
||||
$fa-var-comments: '\f086';
|
||||
$fa-var-comments-o: '\f0e6';
|
||||
$fa-var-compass: '\f14e';
|
||||
$fa-var-compress: '\f066';
|
||||
$fa-var-connectdevelop: '\f20e';
|
||||
$fa-var-contao: '\f26d';
|
||||
$fa-var-copy: '\f0c5';
|
||||
$fa-var-copyright: '\f1f9';
|
||||
$fa-var-creative-commons: '\f25e';
|
||||
$fa-var-credit-card: '\f09d';
|
||||
$fa-var-credit-card-alt: '\f283';
|
||||
$fa-var-crop: '\f125';
|
||||
$fa-var-crosshairs: '\f05b';
|
||||
$fa-var-css3: '\f13c';
|
||||
$fa-var-cube: '\f1b2';
|
||||
$fa-var-cubes: '\f1b3';
|
||||
$fa-var-cut: '\f0c4';
|
||||
$fa-var-cutlery: '\f0f5';
|
||||
$fa-var-dashboard: '\f0e4';
|
||||
$fa-var-dashcube: '\f210';
|
||||
$fa-var-database: '\f1c0';
|
||||
$fa-var-deaf: '\f2a4';
|
||||
$fa-var-deafness: '\f2a4';
|
||||
$fa-var-dedent: '\f03b';
|
||||
$fa-var-delicious: '\f1a5';
|
||||
$fa-var-desktop: '\f108';
|
||||
$fa-var-deviantart: '\f1bd';
|
||||
$fa-var-diamond: '\f219';
|
||||
$fa-var-digg: '\f1a6';
|
||||
$fa-var-dollar: '\f155';
|
||||
$fa-var-dot-circle-o: '\f192';
|
||||
$fa-var-download: '\f019';
|
||||
$fa-var-dribbble: '\f17d';
|
||||
$fa-var-drivers-license: '\f2c2';
|
||||
$fa-var-drivers-license-o: '\f2c3';
|
||||
$fa-var-dropbox: '\f16b';
|
||||
$fa-var-drupal: '\f1a9';
|
||||
$fa-var-edge: '\f282';
|
||||
$fa-var-edit: '\f044';
|
||||
$fa-var-eercast: '\f2da';
|
||||
$fa-var-eject: '\f052';
|
||||
$fa-var-ellipsis-h: '\f141';
|
||||
$fa-var-ellipsis-v: '\f142';
|
||||
$fa-var-empire: '\f1d1';
|
||||
$fa-var-envelope: '\f0e0';
|
||||
$fa-var-envelope-o: '\f003';
|
||||
$fa-var-envelope-open: '\f2b6';
|
||||
$fa-var-envelope-open-o: '\f2b7';
|
||||
$fa-var-envelope-square: '\f199';
|
||||
$fa-var-envira: '\f299';
|
||||
$fa-var-eraser: '\f12d';
|
||||
$fa-var-etsy: '\f2d7';
|
||||
$fa-var-eur: '\f153';
|
||||
$fa-var-euro: '\f153';
|
||||
$fa-var-exchange: '\f0ec';
|
||||
$fa-var-exclamation: '\f12a';
|
||||
$fa-var-exclamation-circle: '\f06a';
|
||||
$fa-var-exclamation-triangle: '\f071';
|
||||
$fa-var-expand: '\f065';
|
||||
$fa-var-expeditedssl: '\f23e';
|
||||
$fa-var-external-link: '\f08e';
|
||||
$fa-var-external-link-square: '\f14c';
|
||||
$fa-var-eye: '\f06e';
|
||||
$fa-var-eye-slash: '\f070';
|
||||
$fa-var-eyedropper: '\f1fb';
|
||||
$fa-var-fa: '\f2b4';
|
||||
$fa-var-facebook: '\f09a';
|
||||
$fa-var-facebook-f: '\f09a';
|
||||
$fa-var-facebook-official: '\f230';
|
||||
$fa-var-facebook-square: '\f082';
|
||||
$fa-var-fast-backward: '\f049';
|
||||
$fa-var-fast-forward: '\f050';
|
||||
$fa-var-fax: '\f1ac';
|
||||
$fa-var-feed: '\f09e';
|
||||
$fa-var-female: '\f182';
|
||||
$fa-var-fighter-jet: '\f0fb';
|
||||
$fa-var-file: '\f15b';
|
||||
$fa-var-file-archive-o: '\f1c6';
|
||||
$fa-var-file-audio-o: '\f1c7';
|
||||
$fa-var-file-code-o: '\f1c9';
|
||||
$fa-var-file-excel-o: '\f1c3';
|
||||
$fa-var-file-image-o: '\f1c5';
|
||||
$fa-var-file-movie-o: '\f1c8';
|
||||
$fa-var-file-o: '\f016';
|
||||
$fa-var-file-pdf-o: '\f1c1';
|
||||
$fa-var-file-photo-o: '\f1c5';
|
||||
$fa-var-file-picture-o: '\f1c5';
|
||||
$fa-var-file-powerpoint-o: '\f1c4';
|
||||
$fa-var-file-sound-o: '\f1c7';
|
||||
$fa-var-file-text: '\f15c';
|
||||
$fa-var-file-text-o: '\f0f6';
|
||||
$fa-var-file-video-o: '\f1c8';
|
||||
$fa-var-file-word-o: '\f1c2';
|
||||
$fa-var-file-zip-o: '\f1c6';
|
||||
$fa-var-files-o: '\f0c5';
|
||||
$fa-var-film: '\f008';
|
||||
$fa-var-filter: '\f0b0';
|
||||
$fa-var-fire: '\f06d';
|
||||
$fa-var-fire-extinguisher: '\f134';
|
||||
$fa-var-firefox: '\f269';
|
||||
$fa-var-first-order: '\f2b0';
|
||||
$fa-var-flag: '\f024';
|
||||
$fa-var-flag-checkered: '\f11e';
|
||||
$fa-var-flag-o: '\f11d';
|
||||
$fa-var-flash: '\f0e7';
|
||||
$fa-var-flask: '\f0c3';
|
||||
$fa-var-flickr: '\f16e';
|
||||
$fa-var-floppy-o: '\f0c7';
|
||||
$fa-var-folder: '\f07b';
|
||||
$fa-var-folder-o: '\f114';
|
||||
$fa-var-folder-open: '\f07c';
|
||||
$fa-var-folder-open-o: '\f115';
|
||||
$fa-var-font: '\f031';
|
||||
$fa-var-font-awesome: '\f2b4';
|
||||
$fa-var-fonticons: '\f280';
|
||||
$fa-var-fort-awesome: '\f286';
|
||||
$fa-var-forumbee: '\f211';
|
||||
$fa-var-forward: '\f04e';
|
||||
$fa-var-foursquare: '\f180';
|
||||
$fa-var-free-code-camp: '\f2c5';
|
||||
$fa-var-frown-o: '\f119';
|
||||
$fa-var-futbol-o: '\f1e3';
|
||||
$fa-var-gamepad: '\f11b';
|
||||
$fa-var-gavel: '\f0e3';
|
||||
$fa-var-gbp: '\f154';
|
||||
$fa-var-ge: '\f1d1';
|
||||
$fa-var-gear: '\f013';
|
||||
$fa-var-gears: '\f085';
|
||||
$fa-var-genderless: '\f22d';
|
||||
$fa-var-get-pocket: '\f265';
|
||||
$fa-var-gg: '\f260';
|
||||
$fa-var-gg-circle: '\f261';
|
||||
$fa-var-gift: '\f06b';
|
||||
$fa-var-git: '\f1d3';
|
||||
$fa-var-git-square: '\f1d2';
|
||||
$fa-var-github: '\f09b';
|
||||
$fa-var-github-alt: '\f113';
|
||||
$fa-var-github-square: '\f092';
|
||||
$fa-var-gitlab: '\f296';
|
||||
$fa-var-gittip: '\f184';
|
||||
$fa-var-glass: '\f000';
|
||||
$fa-var-glide: '\f2a5';
|
||||
$fa-var-glide-g: '\f2a6';
|
||||
$fa-var-globe: '\f0ac';
|
||||
$fa-var-google: '\f1a0';
|
||||
$fa-var-google-plus: '\f0d5';
|
||||
$fa-var-google-plus-circle: '\f2b3';
|
||||
$fa-var-google-plus-official: '\f2b3';
|
||||
$fa-var-google-plus-square: '\f0d4';
|
||||
$fa-var-google-wallet: '\f1ee';
|
||||
$fa-var-graduation-cap: '\f19d';
|
||||
$fa-var-gratipay: '\f184';
|
||||
$fa-var-grav: '\f2d6';
|
||||
$fa-var-group: '\f0c0';
|
||||
$fa-var-h-square: '\f0fd';
|
||||
$fa-var-hacker-news: '\f1d4';
|
||||
$fa-var-hand-grab-o: '\f255';
|
||||
$fa-var-hand-lizard-o: '\f258';
|
||||
$fa-var-hand-o-down: '\f0a7';
|
||||
$fa-var-hand-o-left: '\f0a5';
|
||||
$fa-var-hand-o-right: '\f0a4';
|
||||
$fa-var-hand-o-up: '\f0a6';
|
||||
$fa-var-hand-paper-o: '\f256';
|
||||
$fa-var-hand-peace-o: '\f25b';
|
||||
$fa-var-hand-pointer-o: '\f25a';
|
||||
$fa-var-hand-rock-o: '\f255';
|
||||
$fa-var-hand-scissors-o: '\f257';
|
||||
$fa-var-hand-spock-o: '\f259';
|
||||
$fa-var-hand-stop-o: '\f256';
|
||||
$fa-var-handshake-o: '\f2b5';
|
||||
$fa-var-hard-of-hearing: '\f2a4';
|
||||
$fa-var-hashtag: '\f292';
|
||||
$fa-var-hdd-o: '\f0a0';
|
||||
$fa-var-header: '\f1dc';
|
||||
$fa-var-headphones: '\f025';
|
||||
$fa-var-heart: '\f004';
|
||||
$fa-var-heart-o: '\f08a';
|
||||
$fa-var-heartbeat: '\f21e';
|
||||
$fa-var-history: '\f1da';
|
||||
$fa-var-home: '\f015';
|
||||
$fa-var-hospital-o: '\f0f8';
|
||||
$fa-var-hotel: '\f236';
|
||||
$fa-var-hourglass: '\f254';
|
||||
$fa-var-hourglass-1: '\f251';
|
||||
$fa-var-hourglass-2: '\f252';
|
||||
$fa-var-hourglass-3: '\f253';
|
||||
$fa-var-hourglass-end: '\f253';
|
||||
$fa-var-hourglass-half: '\f252';
|
||||
$fa-var-hourglass-o: '\f250';
|
||||
$fa-var-hourglass-start: '\f251';
|
||||
$fa-var-houzz: '\f27c';
|
||||
$fa-var-html5: '\f13b';
|
||||
$fa-var-i-cursor: '\f246';
|
||||
$fa-var-id-badge: '\f2c1';
|
||||
$fa-var-id-card: '\f2c2';
|
||||
$fa-var-id-card-o: '\f2c3';
|
||||
$fa-var-ils: '\f20b';
|
||||
$fa-var-image: '\f03e';
|
||||
$fa-var-imdb: '\f2d8';
|
||||
$fa-var-inbox: '\f01c';
|
||||
$fa-var-indent: '\f03c';
|
||||
$fa-var-industry: '\f275';
|
||||
$fa-var-info: '\f129';
|
||||
$fa-var-info-circle: '\f05a';
|
||||
$fa-var-inr: '\f156';
|
||||
$fa-var-instagram: '\f16d';
|
||||
$fa-var-institution: '\f19c';
|
||||
$fa-var-internet-explorer: '\f26b';
|
||||
$fa-var-intersex: '\f224';
|
||||
$fa-var-ioxhost: '\f208';
|
||||
$fa-var-italic: '\f033';
|
||||
$fa-var-joomla: '\f1aa';
|
||||
$fa-var-jpy: '\f157';
|
||||
$fa-var-jsfiddle: '\f1cc';
|
||||
$fa-var-key: '\f084';
|
||||
$fa-var-keyboard-o: '\f11c';
|
||||
$fa-var-krw: '\f159';
|
||||
$fa-var-language: '\f1ab';
|
||||
$fa-var-laptop: '\f109';
|
||||
$fa-var-lastfm: '\f202';
|
||||
$fa-var-lastfm-square: '\f203';
|
||||
$fa-var-leaf: '\f06c';
|
||||
$fa-var-leanpub: '\f212';
|
||||
$fa-var-legal: '\f0e3';
|
||||
$fa-var-lemon-o: '\f094';
|
||||
$fa-var-level-down: '\f149';
|
||||
$fa-var-level-up: '\f148';
|
||||
$fa-var-life-bouy: '\f1cd';
|
||||
$fa-var-life-buoy: '\f1cd';
|
||||
$fa-var-life-ring: '\f1cd';
|
||||
$fa-var-life-saver: '\f1cd';
|
||||
$fa-var-lightbulb-o: '\f0eb';
|
||||
$fa-var-line-chart: '\f201';
|
||||
$fa-var-link: '\f0c1';
|
||||
$fa-var-linkedin: '\f0e1';
|
||||
$fa-var-linkedin-square: '\f08c';
|
||||
$fa-var-linode: '\f2b8';
|
||||
$fa-var-linux: '\f17c';
|
||||
$fa-var-list: '\f03a';
|
||||
$fa-var-list-alt: '\f022';
|
||||
$fa-var-list-ol: '\f0cb';
|
||||
$fa-var-list-ul: '\f0ca';
|
||||
$fa-var-location-arrow: '\f124';
|
||||
$fa-var-lock: '\f023';
|
||||
$fa-var-long-arrow-down: '\f175';
|
||||
$fa-var-long-arrow-left: '\f177';
|
||||
$fa-var-long-arrow-right: '\f178';
|
||||
$fa-var-long-arrow-up: '\f176';
|
||||
$fa-var-low-vision: '\f2a8';
|
||||
$fa-var-magic: '\f0d0';
|
||||
$fa-var-magnet: '\f076';
|
||||
$fa-var-mail-forward: '\f064';
|
||||
$fa-var-mail-reply: '\f112';
|
||||
$fa-var-mail-reply-all: '\f122';
|
||||
$fa-var-male: '\f183';
|
||||
$fa-var-map: '\f279';
|
||||
$fa-var-map-marker: '\f041';
|
||||
$fa-var-map-o: '\f278';
|
||||
$fa-var-map-pin: '\f276';
|
||||
$fa-var-map-signs: '\f277';
|
||||
$fa-var-mars: '\f222';
|
||||
$fa-var-mars-double: '\f227';
|
||||
$fa-var-mars-stroke: '\f229';
|
||||
$fa-var-mars-stroke-h: '\f22b';
|
||||
$fa-var-mars-stroke-v: '\f22a';
|
||||
$fa-var-maxcdn: '\f136';
|
||||
$fa-var-meanpath: '\f20c';
|
||||
$fa-var-medium: '\f23a';
|
||||
$fa-var-medkit: '\f0fa';
|
||||
$fa-var-meetup: '\f2e0';
|
||||
$fa-var-meh-o: '\f11a';
|
||||
$fa-var-mercury: '\f223';
|
||||
$fa-var-microchip: '\f2db';
|
||||
$fa-var-microphone: '\f130';
|
||||
$fa-var-microphone-slash: '\f131';
|
||||
$fa-var-minus: '\f068';
|
||||
$fa-var-minus-circle: '\f056';
|
||||
$fa-var-minus-square: '\f146';
|
||||
$fa-var-minus-square-o: '\f147';
|
||||
$fa-var-mixcloud: '\f289';
|
||||
$fa-var-mobile: '\f10b';
|
||||
$fa-var-mobile-phone: '\f10b';
|
||||
$fa-var-modx: '\f285';
|
||||
$fa-var-money: '\f0d6';
|
||||
$fa-var-moon-o: '\f186';
|
||||
$fa-var-mortar-board: '\f19d';
|
||||
$fa-var-motorcycle: '\f21c';
|
||||
$fa-var-mouse-pointer: '\f245';
|
||||
$fa-var-music: '\f001';
|
||||
$fa-var-navicon: '\f0c9';
|
||||
$fa-var-neuter: '\f22c';
|
||||
$fa-var-newspaper-o: '\f1ea';
|
||||
$fa-var-object-group: '\f247';
|
||||
$fa-var-object-ungroup: '\f248';
|
||||
$fa-var-odnoklassniki: '\f263';
|
||||
$fa-var-odnoklassniki-square: '\f264';
|
||||
$fa-var-opencart: '\f23d';
|
||||
$fa-var-openid: '\f19b';
|
||||
$fa-var-opera: '\f26a';
|
||||
$fa-var-optin-monster: '\f23c';
|
||||
$fa-var-outdent: '\f03b';
|
||||
$fa-var-pagelines: '\f18c';
|
||||
$fa-var-paint-brush: '\f1fc';
|
||||
$fa-var-paper-plane: '\f1d8';
|
||||
$fa-var-paper-plane-o: '\f1d9';
|
||||
$fa-var-paperclip: '\f0c6';
|
||||
$fa-var-paragraph: '\f1dd';
|
||||
$fa-var-paste: '\f0ea';
|
||||
$fa-var-pause: '\f04c';
|
||||
$fa-var-pause-circle: '\f28b';
|
||||
$fa-var-pause-circle-o: '\f28c';
|
||||
$fa-var-paw: '\f1b0';
|
||||
$fa-var-paypal: '\f1ed';
|
||||
$fa-var-pencil: '\f040';
|
||||
$fa-var-pencil-square: '\f14b';
|
||||
$fa-var-pencil-square-o: '\f044';
|
||||
$fa-var-percent: '\f295';
|
||||
$fa-var-phone: '\f095';
|
||||
$fa-var-phone-square: '\f098';
|
||||
$fa-var-photo: '\f03e';
|
||||
$fa-var-picture-o: '\f03e';
|
||||
$fa-var-pie-chart: '\f200';
|
||||
$fa-var-pied-piper: '\f2ae';
|
||||
$fa-var-pied-piper-alt: '\f1a8';
|
||||
$fa-var-pied-piper-pp: '\f1a7';
|
||||
$fa-var-pinterest: '\f0d2';
|
||||
$fa-var-pinterest-p: '\f231';
|
||||
$fa-var-pinterest-square: '\f0d3';
|
||||
$fa-var-plane: '\f072';
|
||||
$fa-var-play: '\f04b';
|
||||
$fa-var-play-circle: '\f144';
|
||||
$fa-var-play-circle-o: '\f01d';
|
||||
$fa-var-plug: '\f1e6';
|
||||
$fa-var-plus: '\f067';
|
||||
$fa-var-plus-circle: '\f055';
|
||||
$fa-var-plus-square: '\f0fe';
|
||||
$fa-var-plus-square-o: '\f196';
|
||||
$fa-var-podcast: '\f2ce';
|
||||
$fa-var-power-off: '\f011';
|
||||
$fa-var-print: '\f02f';
|
||||
$fa-var-product-hunt: '\f288';
|
||||
$fa-var-puzzle-piece: '\f12e';
|
||||
$fa-var-qq: '\f1d6';
|
||||
$fa-var-qrcode: '\f029';
|
||||
$fa-var-question: '\f128';
|
||||
$fa-var-question-circle: '\f059';
|
||||
$fa-var-question-circle-o: '\f29c';
|
||||
$fa-var-quora: '\f2c4';
|
||||
$fa-var-quote-left: '\f10d';
|
||||
$fa-var-quote-right: '\f10e';
|
||||
$fa-var-ra: '\f1d0';
|
||||
$fa-var-random: '\f074';
|
||||
$fa-var-ravelry: '\f2d9';
|
||||
$fa-var-rebel: '\f1d0';
|
||||
$fa-var-recycle: '\f1b8';
|
||||
$fa-var-reddit: '\f1a1';
|
||||
$fa-var-reddit-alien: '\f281';
|
||||
$fa-var-reddit-square: '\f1a2';
|
||||
$fa-var-refresh: '\f021';
|
||||
$fa-var-registered: '\f25d';
|
||||
$fa-var-remove: '\f00d';
|
||||
$fa-var-renren: '\f18b';
|
||||
$fa-var-reorder: '\f0c9';
|
||||
$fa-var-repeat: '\f01e';
|
||||
$fa-var-reply: '\f112';
|
||||
$fa-var-reply-all: '\f122';
|
||||
$fa-var-resistance: '\f1d0';
|
||||
$fa-var-retweet: '\f079';
|
||||
$fa-var-rmb: '\f157';
|
||||
$fa-var-road: '\f018';
|
||||
$fa-var-rocket: '\f135';
|
||||
$fa-var-rotate-left: '\f0e2';
|
||||
$fa-var-rotate-right: '\f01e';
|
||||
$fa-var-rouble: '\f158';
|
||||
$fa-var-rss: '\f09e';
|
||||
$fa-var-rss-square: '\f143';
|
||||
$fa-var-rub: '\f158';
|
||||
$fa-var-ruble: '\f158';
|
||||
$fa-var-rupee: '\f156';
|
||||
$fa-var-s15: '\f2cd';
|
||||
$fa-var-safari: '\f267';
|
||||
$fa-var-save: '\f0c7';
|
||||
$fa-var-scissors: '\f0c4';
|
||||
$fa-var-scribd: '\f28a';
|
||||
$fa-var-search: '\f002';
|
||||
$fa-var-search-minus: '\f010';
|
||||
$fa-var-search-plus: '\f00e';
|
||||
$fa-var-sellsy: '\f213';
|
||||
$fa-var-send: '\f1d8';
|
||||
$fa-var-send-o: '\f1d9';
|
||||
$fa-var-server: '\f233';
|
||||
$fa-var-share: '\f064';
|
||||
$fa-var-share-alt: '\f1e0';
|
||||
$fa-var-share-alt-square: '\f1e1';
|
||||
$fa-var-share-square: '\f14d';
|
||||
$fa-var-share-square-o: '\f045';
|
||||
$fa-var-shekel: '\f20b';
|
||||
$fa-var-sheqel: '\f20b';
|
||||
$fa-var-shield: '\f132';
|
||||
$fa-var-ship: '\f21a';
|
||||
$fa-var-shirtsinbulk: '\f214';
|
||||
$fa-var-shopping-bag: '\f290';
|
||||
$fa-var-shopping-basket: '\f291';
|
||||
$fa-var-shopping-cart: '\f07a';
|
||||
$fa-var-shower: '\f2cc';
|
||||
$fa-var-sign-in: '\f090';
|
||||
$fa-var-sign-language: '\f2a7';
|
||||
$fa-var-sign-out: '\f08b';
|
||||
$fa-var-signal: '\f012';
|
||||
$fa-var-signing: '\f2a7';
|
||||
$fa-var-simplybuilt: '\f215';
|
||||
$fa-var-sitemap: '\f0e8';
|
||||
$fa-var-skyatlas: '\f216';
|
||||
$fa-var-skype: '\f17e';
|
||||
$fa-var-slack: '\f198';
|
||||
$fa-var-sliders: '\f1de';
|
||||
$fa-var-slideshare: '\f1e7';
|
||||
$fa-var-smile-o: '\f118';
|
||||
$fa-var-snapchat: '\f2ab';
|
||||
$fa-var-snapchat-ghost: '\f2ac';
|
||||
$fa-var-snapchat-square: '\f2ad';
|
||||
$fa-var-snowflake-o: '\f2dc';
|
||||
$fa-var-soccer-ball-o: '\f1e3';
|
||||
$fa-var-sort: '\f0dc';
|
||||
$fa-var-sort-alpha-asc: '\f15d';
|
||||
$fa-var-sort-alpha-desc: '\f15e';
|
||||
$fa-var-sort-amount-asc: '\f160';
|
||||
$fa-var-sort-amount-desc: '\f161';
|
||||
$fa-var-sort-asc: '\f0de';
|
||||
$fa-var-sort-desc: '\f0dd';
|
||||
$fa-var-sort-down: '\f0dd';
|
||||
$fa-var-sort-numeric-asc: '\f162';
|
||||
$fa-var-sort-numeric-desc: '\f163';
|
||||
$fa-var-sort-up: '\f0de';
|
||||
$fa-var-soundcloud: '\f1be';
|
||||
$fa-var-space-shuttle: '\f197';
|
||||
$fa-var-spinner: '\f110';
|
||||
$fa-var-spoon: '\f1b1';
|
||||
$fa-var-spotify: '\f1bc';
|
||||
$fa-var-square: '\f0c8';
|
||||
$fa-var-square-o: '\f096';
|
||||
$fa-var-stack-exchange: '\f18d';
|
||||
$fa-var-stack-overflow: '\f16c';
|
||||
$fa-var-star: '\f005';
|
||||
$fa-var-star-half: '\f089';
|
||||
$fa-var-star-half-empty: '\f123';
|
||||
$fa-var-star-half-full: '\f123';
|
||||
$fa-var-star-half-o: '\f123';
|
||||
$fa-var-star-o: '\f006';
|
||||
$fa-var-steam: '\f1b6';
|
||||
$fa-var-steam-square: '\f1b7';
|
||||
$fa-var-step-backward: '\f048';
|
||||
$fa-var-step-forward: '\f051';
|
||||
$fa-var-stethoscope: '\f0f1';
|
||||
$fa-var-sticky-note: '\f249';
|
||||
$fa-var-sticky-note-o: '\f24a';
|
||||
$fa-var-stop: '\f04d';
|
||||
$fa-var-stop-circle: '\f28d';
|
||||
$fa-var-stop-circle-o: '\f28e';
|
||||
$fa-var-street-view: '\f21d';
|
||||
$fa-var-strikethrough: '\f0cc';
|
||||
$fa-var-stumbleupon: '\f1a4';
|
||||
$fa-var-stumbleupon-circle: '\f1a3';
|
||||
$fa-var-subscript: '\f12c';
|
||||
$fa-var-subway: '\f239';
|
||||
$fa-var-suitcase: '\f0f2';
|
||||
$fa-var-sun-o: '\f185';
|
||||
$fa-var-superpowers: '\f2dd';
|
||||
$fa-var-superscript: '\f12b';
|
||||
$fa-var-support: '\f1cd';
|
||||
$fa-var-table: '\f0ce';
|
||||
$fa-var-tablet: '\f10a';
|
||||
$fa-var-tachometer: '\f0e4';
|
||||
$fa-var-tag: '\f02b';
|
||||
$fa-var-tags: '\f02c';
|
||||
$fa-var-tasks: '\f0ae';
|
||||
$fa-var-taxi: '\f1ba';
|
||||
$fa-var-telegram: '\f2c6';
|
||||
$fa-var-television: '\f26c';
|
||||
$fa-var-tencent-weibo: '\f1d5';
|
||||
$fa-var-terminal: '\f120';
|
||||
$fa-var-text-height: '\f034';
|
||||
$fa-var-text-width: '\f035';
|
||||
$fa-var-th: '\f00a';
|
||||
$fa-var-th-large: '\f009';
|
||||
$fa-var-th-list: '\f00b';
|
||||
$fa-var-themeisle: '\f2b2';
|
||||
$fa-var-thermometer: '\f2c7';
|
||||
$fa-var-thermometer-0: '\f2cb';
|
||||
$fa-var-thermometer-1: '\f2ca';
|
||||
$fa-var-thermometer-2: '\f2c9';
|
||||
$fa-var-thermometer-3: '\f2c8';
|
||||
$fa-var-thermometer-4: '\f2c7';
|
||||
$fa-var-thermometer-empty: '\f2cb';
|
||||
$fa-var-thermometer-full: '\f2c7';
|
||||
$fa-var-thermometer-half: '\f2c9';
|
||||
$fa-var-thermometer-quarter: '\f2ca';
|
||||
$fa-var-thermometer-three-quarters: '\f2c8';
|
||||
$fa-var-thumb-tack: '\f08d';
|
||||
$fa-var-thumbs-down: '\f165';
|
||||
$fa-var-thumbs-o-down: '\f088';
|
||||
$fa-var-thumbs-o-up: '\f087';
|
||||
$fa-var-thumbs-up: '\f164';
|
||||
$fa-var-ticket: '\f145';
|
||||
$fa-var-times: '\f00d';
|
||||
$fa-var-times-circle: '\f057';
|
||||
$fa-var-times-circle-o: '\f05c';
|
||||
$fa-var-times-rectangle: '\f2d3';
|
||||
$fa-var-times-rectangle-o: '\f2d4';
|
||||
$fa-var-tint: '\f043';
|
||||
$fa-var-toggle-down: '\f150';
|
||||
$fa-var-toggle-left: '\f191';
|
||||
$fa-var-toggle-off: '\f204';
|
||||
$fa-var-toggle-on: '\f205';
|
||||
$fa-var-toggle-right: '\f152';
|
||||
$fa-var-toggle-up: '\f151';
|
||||
$fa-var-trademark: '\f25c';
|
||||
$fa-var-train: '\f238';
|
||||
$fa-var-transgender: '\f224';
|
||||
$fa-var-transgender-alt: '\f225';
|
||||
$fa-var-trash: '\f1f8';
|
||||
$fa-var-trash-o: '\f014';
|
||||
$fa-var-tree: '\f1bb';
|
||||
$fa-var-trello: '\f181';
|
||||
$fa-var-tripadvisor: '\f262';
|
||||
$fa-var-trophy: '\f091';
|
||||
$fa-var-truck: '\f0d1';
|
||||
$fa-var-try: '\f195';
|
||||
$fa-var-tty: '\f1e4';
|
||||
$fa-var-tumblr: '\f173';
|
||||
$fa-var-tumblr-square: '\f174';
|
||||
$fa-var-turkish-lira: '\f195';
|
||||
$fa-var-tv: '\f26c';
|
||||
$fa-var-twitch: '\f1e8';
|
||||
$fa-var-twitter: '\f099';
|
||||
$fa-var-twitter-square: '\f081';
|
||||
$fa-var-umbrella: '\f0e9';
|
||||
$fa-var-underline: '\f0cd';
|
||||
$fa-var-undo: '\f0e2';
|
||||
$fa-var-universal-access: '\f29a';
|
||||
$fa-var-university: '\f19c';
|
||||
$fa-var-unlink: '\f127';
|
||||
$fa-var-unlock: '\f09c';
|
||||
$fa-var-unlock-alt: '\f13e';
|
||||
$fa-var-unsorted: '\f0dc';
|
||||
$fa-var-upload: '\f093';
|
||||
$fa-var-usb: '\f287';
|
||||
$fa-var-usd: '\f155';
|
||||
$fa-var-user: '\f007';
|
||||
$fa-var-user-circle: '\f2bd';
|
||||
$fa-var-user-circle-o: '\f2be';
|
||||
$fa-var-user-md: '\f0f0';
|
||||
$fa-var-user-o: '\f2c0';
|
||||
$fa-var-user-plus: '\f234';
|
||||
$fa-var-user-secret: '\f21b';
|
||||
$fa-var-user-times: '\f235';
|
||||
$fa-var-users: '\f0c0';
|
||||
$fa-var-vcard: '\f2bb';
|
||||
$fa-var-vcard-o: '\f2bc';
|
||||
$fa-var-venus: '\f221';
|
||||
$fa-var-venus-double: '\f226';
|
||||
$fa-var-venus-mars: '\f228';
|
||||
$fa-var-viacoin: '\f237';
|
||||
$fa-var-viadeo: '\f2a9';
|
||||
$fa-var-viadeo-square: '\f2aa';
|
||||
$fa-var-video-camera: '\f03d';
|
||||
$fa-var-vimeo: '\f27d';
|
||||
$fa-var-vimeo-square: '\f194';
|
||||
$fa-var-vine: '\f1ca';
|
||||
$fa-var-vk: '\f189';
|
||||
$fa-var-volume-control-phone: '\f2a0';
|
||||
$fa-var-volume-down: '\f027';
|
||||
$fa-var-volume-off: '\f026';
|
||||
$fa-var-volume-up: '\f028';
|
||||
$fa-var-warning: '\f071';
|
||||
$fa-var-wechat: '\f1d7';
|
||||
$fa-var-weibo: '\f18a';
|
||||
$fa-var-weixin: '\f1d7';
|
||||
$fa-var-whatsapp: '\f232';
|
||||
$fa-var-wheelchair: '\f193';
|
||||
$fa-var-wheelchair-alt: '\f29b';
|
||||
$fa-var-wifi: '\f1eb';
|
||||
$fa-var-wikipedia-w: '\f266';
|
||||
$fa-var-window-close: '\f2d3';
|
||||
$fa-var-window-close-o: '\f2d4';
|
||||
$fa-var-window-maximize: '\f2d0';
|
||||
$fa-var-window-minimize: '\f2d1';
|
||||
$fa-var-window-restore: '\f2d2';
|
||||
$fa-var-windows: '\f17a';
|
||||
$fa-var-won: '\f159';
|
||||
$fa-var-wordpress: '\f19a';
|
||||
$fa-var-wpbeginner: '\f297';
|
||||
$fa-var-wpexplorer: '\f2de';
|
||||
$fa-var-wpforms: '\f298';
|
||||
$fa-var-wrench: '\f0ad';
|
||||
$fa-var-xing: '\f168';
|
||||
$fa-var-xing-square: '\f169';
|
||||
$fa-var-y-combinator: '\f23b';
|
||||
$fa-var-y-combinator-square: '\f1d4';
|
||||
$fa-var-yahoo: '\f19e';
|
||||
$fa-var-yc: '\f23b';
|
||||
$fa-var-yc-square: '\f1d4';
|
||||
$fa-var-yelp: '\f1e9';
|
||||
$fa-var-yen: '\f157';
|
||||
$fa-var-yoast: '\f2b1';
|
||||
$fa-var-youtube: '\f167';
|
||||
$fa-var-youtube-play: '\f16a';
|
||||
$fa-var-youtube-square: '\f166';
|
18
public/font-awesome-4.7.0/scss/font-awesome.scss
vendored
Normal file
18
public/font-awesome-4.7.0/scss/font-awesome.scss
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
/*!
|
||||
* Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome
|
||||
* License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
|
||||
*/
|
||||
|
||||
@import 'variables';
|
||||
@import 'mixins';
|
||||
@import 'path';
|
||||
@import 'core';
|
||||
@import 'larger';
|
||||
@import 'fixed-width';
|
||||
@import 'list';
|
||||
@import 'bordered-pulled';
|
||||
@import 'animated';
|
||||
@import 'rotated-flipped';
|
||||
@import 'stacked';
|
||||
@import 'icons';
|
||||
@import 'screen-reader';
|
19
public/iconfont/iconfont.css
Normal file
19
public/iconfont/iconfont.css
Normal file
@ -0,0 +1,19 @@
|
||||
@font-face {
|
||||
font-family: "iconfont"; /* Project id 3814452 */
|
||||
src: url('iconfont.woff2?t=1670405177902') format('woff2'),
|
||||
url('iconfont.woff?t=1670405177902') format('woff'),
|
||||
url('iconfont.ttf?t=1670405177902') format('truetype');
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
font-family: "iconfont" !important;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.icon-enterprise:before {
|
||||
content: "\e724";
|
||||
}
|
||||
|
BIN
public/iconfont/iconfont.ttf
Normal file
BIN
public/iconfont/iconfont.ttf
Normal file
Binary file not shown.
BIN
public/iconfont/iconfont.woff
Normal file
BIN
public/iconfont/iconfont.woff
Normal file
Binary file not shown.
BIN
public/iconfont/iconfont.woff2
Normal file
BIN
public/iconfont/iconfont.woff2
Normal file
Binary file not shown.
36
public/iframe/index.html
Normal file
36
public/iframe/index.html
Normal file
@ -0,0 +1,36 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title></title>
|
||||
<script></script>
|
||||
<style>
|
||||
html,
|
||||
body,
|
||||
.box {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.iframe {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
margin-top: -124px;
|
||||
height: calc(100% + 124px);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="box">
|
||||
<iframe id="iframe" frameborder="no" class="iframe" src=""></iframe>
|
||||
</div>
|
||||
</body>
|
||||
<script>
|
||||
const root = 'iframe/index.html?url='
|
||||
const href = window.location.href
|
||||
const idx = href.indexOf(root)
|
||||
document.getElementById('iframe').src = href.substring(idx + root.length)
|
||||
</script>
|
||||
</html>
|
36
src/App.vue
Normal file
36
src/App.vue
Normal file
@ -0,0 +1,36 @@
|
||||
<script setup lang="ts">
|
||||
// import enUS from '@arco-design/web-vue/es/locale/lang/en-us'
|
||||
import { provide } from 'vue'
|
||||
import { getStore } from '@/utils/storage'
|
||||
import systemInfo from '@/mixins/system_info'
|
||||
import { useVersionUpdateListener } from '@/hooks/version'
|
||||
|
||||
if (getStore('darkMode') === true) {
|
||||
document.body.setAttribute('arco-theme', 'dark')
|
||||
}
|
||||
provide('systemInfo', systemInfo)
|
||||
onMounted(() => {
|
||||
useVersionUpdateListener()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-config-provider> <router-view></router-view></a-config-provider>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
html,
|
||||
body,
|
||||
#app {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
#app {
|
||||
font-family: Avenir, Helvetica, Arial, sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
background-color: var(--color-bg-3);
|
||||
}
|
||||
</style>
|
25
src/api/api.ts
Normal file
25
src/api/api.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import axios from '@/utils/axios'
|
||||
import { encrypt } from '@/utils/crypto'
|
||||
|
||||
export function login(form: any) {
|
||||
// 处理逻辑
|
||||
const timestamp = new Date().getTime().toString()
|
||||
return axios.post('/sys/api/login', {
|
||||
secret: timestamp,
|
||||
captchaVerification: form.captchaVerification,
|
||||
phone: encrypt(timestamp + form.phone),
|
||||
password: encrypt(timestamp + form.password)
|
||||
})
|
||||
}
|
||||
|
||||
export function forget(form: any) {
|
||||
// 处理逻辑
|
||||
const timestamp = new Date().getTime().toString()
|
||||
return axios.post('/sys/api/forget', {
|
||||
secret: timestamp,
|
||||
email: encrypt(timestamp + form.email),
|
||||
password: encrypt(timestamp + form.password),
|
||||
code: encrypt(timestamp + form.code),
|
||||
inviteCode: form.inviteCode
|
||||
})
|
||||
}
|
45
src/api/upms/dept.ts
Normal file
45
src/api/upms/dept.ts
Normal file
@ -0,0 +1,45 @@
|
||||
import axios from '@/utils/axios'
|
||||
|
||||
/**
|
||||
* 获取所有部门
|
||||
* @returns Promise
|
||||
*/
|
||||
export function fetchAllTree() {
|
||||
return axios.post('/sys/dept/fetch/all')
|
||||
}
|
||||
/**
|
||||
* 获取所有部门包含用户
|
||||
* @returns Promise
|
||||
*/
|
||||
export function fetchUserTree() {
|
||||
return axios.post('/sys/dept/fetch/user')
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过部门id获取用户ids
|
||||
*
|
||||
* @param deptId 部门id
|
||||
* @return 用户ids
|
||||
* @date 2022.12.12
|
||||
*/
|
||||
export function userIdsByDeptId(deptId: string) {
|
||||
return axios.post(`/sys/dept/user/ids/by/${deptId}`)
|
||||
}
|
||||
|
||||
/**
|
||||
* 重新设置部门成员
|
||||
* @param deptId 部门id
|
||||
* @param userIds 新成员ids
|
||||
*/
|
||||
export function resetDeptUser(deptId: string, userIds: string[]) {
|
||||
return axios.post('/sys/dept/reset/dept/user', { id: deptId, userIds })
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除部门中某个成员
|
||||
* @param deptId 部门id
|
||||
* @param userId 成员id
|
||||
*/
|
||||
export function removeDeptUser(deptId: string, userId: string) {
|
||||
return axios.post('/sys/dept/remove/dept/user', { deptId, userId })
|
||||
}
|
30
src/api/upms/group.ts
Normal file
30
src/api/upms/group.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import axios from '@/utils/axios'
|
||||
|
||||
/**
|
||||
* 通过id获取用户ids
|
||||
*
|
||||
* @param groupId id
|
||||
* @return 用户ids
|
||||
* @date 2022.12.12
|
||||
*/
|
||||
export function userIdsByGroupId(groupId: string) {
|
||||
return axios.post(`/sys/group/user/ids/by/${groupId}`)
|
||||
}
|
||||
|
||||
/**
|
||||
* 重新设置成员
|
||||
* @param groupId id
|
||||
* @param userIds 新成员ids
|
||||
*/
|
||||
export function userReset(groupId: string, userIds: string[]) {
|
||||
return axios.post('/sys/group/user/reset', { id: groupId, userIds })
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除某个成员
|
||||
* @param groupId id
|
||||
* @param userId 成员id
|
||||
*/
|
||||
export function userRemove(groupId: string, userId: string) {
|
||||
return axios.post('/sys/group/user/remove', { groupId, userId })
|
||||
}
|
26
src/api/upms/menu.ts
Normal file
26
src/api/upms/menu.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import axios from '@/utils/axios'
|
||||
|
||||
/**
|
||||
* 获取有权限的菜单树
|
||||
* @returns Promise
|
||||
*/
|
||||
// eslint-disable-next-line import/prefer-default-export
|
||||
export function getMenuTree() {
|
||||
return axios.post('/sys/menu/tree')
|
||||
}
|
||||
|
||||
export function getMenuTreeByRoleId(roleId: string) {
|
||||
return axios.post(`/sys/menu/tree/role/${roleId}`)
|
||||
}
|
||||
|
||||
export function editRoleMenus(roleId: string, menuIds: Array<string>) {
|
||||
return axios.post(`/sys/menu/role/${roleId}`, menuIds)
|
||||
}
|
||||
|
||||
export function getMenuTreeByPackageId(packageId: string) {
|
||||
return axios.post(`/sys/menu/tree/package/${packageId}`)
|
||||
}
|
||||
|
||||
export function editPackageMenus(packageId: string, menuIds: Array<string>) {
|
||||
return axios.post(`/sys/menu/package/${packageId}`, menuIds)
|
||||
}
|
19
src/api/upms/notify-channel.ts
Normal file
19
src/api/upms/notify-channel.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { SysNotifyChannel } from '@/entity/upms/notify-channel'
|
||||
import axios from '@/utils/axios'
|
||||
|
||||
const baseUrl = 'sys/notify/channel'
|
||||
/**
|
||||
* 获取所有消息通道配置
|
||||
* @returns Array<SysNotifyChannel>
|
||||
*/
|
||||
export function getConfig() {
|
||||
return axios.post(`${baseUrl}/get/config`)
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑某项配置
|
||||
* @param data 数据{type,config}
|
||||
*/
|
||||
export function editConfig(data: SysNotifyChannel) {
|
||||
return axios.post(`${baseUrl}/edit/config`, data)
|
||||
}
|
10
src/api/upms/user.ts
Normal file
10
src/api/upms/user.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import axios from '@/utils/axios'
|
||||
|
||||
/**
|
||||
* 修改个人密码
|
||||
* @param password 旧密码
|
||||
* @param newPassword 新密码
|
||||
*/
|
||||
export function updatePassword(password: string, newPassword: string) {
|
||||
return axios.post('/sys/user/password', { password, newPassword })
|
||||
}
|
71
src/assets/css/arco.scss
Normal file
71
src/assets/css/arco.scss
Normal file
@ -0,0 +1,71 @@
|
||||
|
||||
// 设置暗黑模式下spin的背景色透明
|
||||
body[arco-theme='dark'] {
|
||||
.arco-spin-mask {
|
||||
background-color: unset !important;
|
||||
}
|
||||
}
|
||||
.arco-modal-body {
|
||||
max-height: calc(100vh - 48px - 65px - 48px);
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
// 未引入tailwind需要此
|
||||
// width: calc(100% - 40px);
|
||||
}
|
||||
|
||||
@media screen and (max-width: 530px) {
|
||||
.arco-modal {
|
||||
width: 94vw;
|
||||
}
|
||||
}
|
||||
|
||||
.arco-scrollbar-thumb-direction-vertical .arco-scrollbar-thumb-bar {
|
||||
width: 7px;
|
||||
margin: 0 5px;
|
||||
}
|
||||
|
||||
.arco-popconfirm-content {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
// 自定义arco表格滚动条样式
|
||||
.arco-table-content-scroll-x,
|
||||
.arco-table-content-scroll-y,
|
||||
.arco-table.arco-table-empty .arco-table-header {
|
||||
/*定义滚动条高宽及背景 高宽分别对应横竖滚动条的尺寸*/
|
||||
&::-webkit-scrollbar {
|
||||
background-color: var(--color-fill-1);
|
||||
border-bottom-right-radius: var(--border-radius-medium);
|
||||
}
|
||||
/*定义滚动条轨道 内阴影+圆角*/
|
||||
&::-webkit-scrollbar-track {
|
||||
border-radius: 6px;
|
||||
}
|
||||
/*定义滑块 内阴影+圆角*/
|
||||
&::-webkit-scrollbar-thumb {
|
||||
border-radius: 6px;
|
||||
background-color: var(--color-neutral-4);
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
background-color: var(--color-neutral-5);
|
||||
}
|
||||
&:active {
|
||||
background-color: var(--color-neutral-6);
|
||||
}
|
||||
}
|
||||
}
|
||||
.arco-table-content-scroll-x,
|
||||
.arco-table.arco-table-empty .arco-table-header {
|
||||
&::-webkit-scrollbar {
|
||||
height: 9px;
|
||||
}
|
||||
}
|
||||
.arco-table-content-scroll-y {
|
||||
&::-webkit-scrollbar {
|
||||
width: 9px;
|
||||
}
|
||||
}
|
||||
|
||||
.arco-trigger-popup{
|
||||
white-space:pre-wrap;
|
||||
}
|
274
src/assets/css/flex.scss
Normal file
274
src/assets/css/flex.scss
Normal file
@ -0,0 +1,274 @@
|
||||
.un-select {
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
-webkit-user-drag: none;
|
||||
img {
|
||||
-webkit-user-drag: none;
|
||||
}
|
||||
}
|
||||
.flex-view {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.flex {
|
||||
display: flex;
|
||||
}
|
||||
/* Flexbox 布局 */
|
||||
/* Flex Direction */
|
||||
.flex-row {
|
||||
@extend .flex-view;
|
||||
flex-direction: row;
|
||||
}
|
||||
.flex-row-reverse {
|
||||
flex-direction: row-reverse !important;
|
||||
@extend .flex-view;
|
||||
}
|
||||
.flex-column {
|
||||
flex-direction: column !important;
|
||||
@extend .flex-view;
|
||||
}
|
||||
.flex-column-reverse {
|
||||
flex-direction: column-reverse !important;
|
||||
@extend .flex-view;
|
||||
}
|
||||
/* Flex Wrap */
|
||||
.flex-nowrap {
|
||||
flex-wrap: nowrap !important;
|
||||
@extend .flex-view;
|
||||
}
|
||||
.flex-wrap {
|
||||
flex-wrap: wrap !important;
|
||||
@extend .flex-view;
|
||||
}
|
||||
.flex-wrap-reverse {
|
||||
flex-wrap: wrap-reverse !important;
|
||||
@extend .flex-view;
|
||||
}
|
||||
/* Align Items */
|
||||
.align-stretch {
|
||||
align-items: stretch !important;
|
||||
@extend .flex-view;
|
||||
}
|
||||
.align-start {
|
||||
align-items: flex-start !important;
|
||||
@extend .flex-view;
|
||||
}
|
||||
.align-center {
|
||||
align-items: center !important;
|
||||
@extend .flex-view;
|
||||
}
|
||||
.align-end {
|
||||
align-items: flex-end !important;
|
||||
@extend .flex-view;
|
||||
}
|
||||
/* Justify Content */
|
||||
.justify-start {
|
||||
justify-content: flex-start !important;
|
||||
@extend .flex-view;
|
||||
}
|
||||
.justify-center {
|
||||
justify-content: center !important;
|
||||
@extend .flex-view;
|
||||
}
|
||||
.justify-end {
|
||||
justify-content: flex-end !important;
|
||||
@extend .flex-view;
|
||||
}
|
||||
.justify-between {
|
||||
justify-content: space-between !important;
|
||||
@extend .flex-view;
|
||||
}
|
||||
.justify-around {
|
||||
justify-content: space-around !important;
|
||||
@extend .flex-view;
|
||||
}
|
||||
/* 字体粗细 */
|
||||
.text-bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
/* 文本对齐 */
|
||||
.text-left {
|
||||
text-align: left;
|
||||
}
|
||||
.text-center {
|
||||
text-align: center;
|
||||
}
|
||||
.text-right {
|
||||
text-align: right;
|
||||
}
|
||||
/* 文本装饰 */
|
||||
.text-underline {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.text-through {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
/* flex */
|
||||
.flex-1 {
|
||||
flex: 1 !important;
|
||||
}
|
||||
.flex-2 {
|
||||
flex: 2 !important;
|
||||
}
|
||||
.flex-3 {
|
||||
flex: 3 !important;
|
||||
}
|
||||
.flex-4 {
|
||||
flex: 4 !important;
|
||||
}
|
||||
.flex-5 {
|
||||
flex: 5 !important;
|
||||
}
|
||||
.flex-6 {
|
||||
flex: 6 !important;
|
||||
}
|
||||
.flex-7 {
|
||||
flex: 7 !important;
|
||||
}
|
||||
.flex-8 {
|
||||
flex: 8 !important;
|
||||
}
|
||||
/* 文本大小 */
|
||||
.text-xs {
|
||||
font-size: 12px !important;
|
||||
}
|
||||
.text-sm {
|
||||
font-size: 14px !important;
|
||||
}
|
||||
.text-md {
|
||||
font-size: 16px !important;
|
||||
}
|
||||
.text-lg {
|
||||
font-size: 20px !important;
|
||||
}
|
||||
.text-xl {
|
||||
font-size: 24px !important;
|
||||
}
|
||||
/* 行高 */
|
||||
.leading-xs {
|
||||
line-height: 14px;
|
||||
}
|
||||
.leading-sm {
|
||||
line-height: 16px;
|
||||
}
|
||||
.leading-md {
|
||||
line-height: 20px;
|
||||
}
|
||||
.leading-lg {
|
||||
line-height: 24px;
|
||||
}
|
||||
.leading-xl {
|
||||
line-height: 28px;
|
||||
}
|
||||
|
||||
@mixin lines($num) {
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: $num;
|
||||
lines: $num;
|
||||
}
|
||||
/* 超出行省略 */
|
||||
.lines-1 {
|
||||
@include lines(1);
|
||||
}
|
||||
.lines-2 {
|
||||
@include lines(2);
|
||||
}
|
||||
.lines-3 {
|
||||
@include lines(3);
|
||||
}
|
||||
.lines-4 {
|
||||
@include lines(4);
|
||||
}
|
||||
.lines-5 {
|
||||
@include lines(5);
|
||||
}
|
||||
/* 定位 */
|
||||
.absolute {
|
||||
position: absolute !important;
|
||||
}
|
||||
.absolute-screen {
|
||||
position: absolute !important;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
z-index: 998;
|
||||
}
|
||||
.fixed {
|
||||
position: fixed !important;
|
||||
}
|
||||
.fixed-screen {
|
||||
position: fixed !important;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
z-index: 999;
|
||||
}
|
||||
.sticky {
|
||||
position: sticky !important;
|
||||
top: 0;
|
||||
z-index: 969;
|
||||
}
|
||||
/* 内外边距 */
|
||||
$margin-map: (
|
||||
xs: 8px,
|
||||
sm: 16px,
|
||||
md: 24px,
|
||||
lg: 32px,
|
||||
xl: 48px
|
||||
);
|
||||
@each $parameter in xs, sm, md, lg, xl {
|
||||
.ma-#{$parameter} {
|
||||
margin: map-get($map: $margin-map, $key: $parameter);
|
||||
}
|
||||
.mt-#{$parameter} {
|
||||
margin-top: map-get($map: $margin-map, $key: $parameter);
|
||||
}
|
||||
.mb-#{$parameter} {
|
||||
margin-bottom: map-get($map: $margin-map, $key: $parameter);
|
||||
}
|
||||
.ml-#{$parameter} {
|
||||
margin-left: map-get($map: $margin-map, $key: $parameter);
|
||||
}
|
||||
.mr-#{$parameter} {
|
||||
margin-right: map-get($map: $margin-map, $key: $parameter);
|
||||
}
|
||||
.mx-#{$parameter} {
|
||||
margin-left: map-get($map: $margin-map, $key: $parameter);
|
||||
margin-right: map-get($map: $margin-map, $key: $parameter);
|
||||
}
|
||||
.my-#{$parameter} {
|
||||
margin-top: map-get($map: $margin-map, $key: $parameter);
|
||||
margin-bottom: map-get($map: $margin-map, $key: $parameter);
|
||||
}
|
||||
.pa-#{$parameter} {
|
||||
padding: map-get($map: $margin-map, $key: $parameter);
|
||||
}
|
||||
.pt-#{$parameter} {
|
||||
padding-top: map-get($map: $margin-map, $key: $parameter);
|
||||
}
|
||||
.pb-#{$parameter} {
|
||||
padding-bottom: map-get($map: $margin-map, $key: $parameter);
|
||||
}
|
||||
.pl-#{$parameter} {
|
||||
padding-left: map-get($map: $margin-map, $key: $parameter);
|
||||
}
|
||||
.pr-#{$parameter} {
|
||||
padding-right: map-get($map: $margin-map, $key: $parameter);
|
||||
}
|
||||
.px-#{$parameter} {
|
||||
padding-left: map-get($map: $margin-map, $key: $parameter);
|
||||
padding-right: map-get($map: $margin-map, $key: $parameter);
|
||||
}
|
||||
.py-#{$parameter} {
|
||||
padding-top: map-get($map: $margin-map, $key: $parameter);
|
||||
padding-bottom: map-get($map: $margin-map, $key: $parameter);
|
||||
}
|
||||
}
|
28
src/assets/css/tailwind.css
Normal file
28
src/assets/css/tailwind.css
Normal file
@ -0,0 +1,28 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
/* Flexbox 布局 */
|
||||
/* Flex Direction */
|
||||
.flex-row {
|
||||
display: flex;
|
||||
}
|
||||
.flex-row-reverse {
|
||||
display: flex;
|
||||
}
|
||||
.flex-col {
|
||||
display: flex;
|
||||
}
|
||||
.flex-col-reverse {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
/* 解决冲突 */
|
||||
.arco-switch{
|
||||
background-color: var(--color-fill-4);
|
||||
-webkit-appearance:unset;
|
||||
background-image:unset;
|
||||
}
|
||||
.arco-switch-checked {
|
||||
background-color: rgb(var(--primary-6));
|
||||
}
|
BIN
src/assets/images/login-arrow.png
Normal file
BIN
src/assets/images/login-arrow.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 480 B |
BIN
src/assets/images/login-logo.png
Normal file
BIN
src/assets/images/login-logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.0 KiB |
14
src/axios.d.ts
vendored
Normal file
14
src/axios.d.ts
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
import { AxiosRequestConfig } from 'axios'
|
||||
|
||||
declare module 'axios' {
|
||||
export interface AxiosInstance {
|
||||
<T = any>(config: AxiosRequestConfig): Promise<T>
|
||||
request<T = any>(config: AxiosRequestConfig): Promise<T>
|
||||
get<T = any>(url: string, config?: AxiosRequestConfig): Promise<T>
|
||||
delete<T = any>(url: string, config?: AxiosRequestConfig): Promise<T>
|
||||
head<T = any>(url: string, config?: AxiosRequestConfig): Promise<T>
|
||||
post<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T>
|
||||
put<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T>
|
||||
patch<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T>
|
||||
}
|
||||
}
|
62
src/components/_hooks/use-tree-search.ts
Normal file
62
src/components/_hooks/use-tree-search.ts
Normal file
@ -0,0 +1,62 @@
|
||||
import { computed, ref } from 'vue'
|
||||
|
||||
const searchData = (val: string | undefined, data: any[]): any[] => {
|
||||
if (!val) {
|
||||
return data
|
||||
}
|
||||
const result: any[] = []
|
||||
data.forEach((item) => {
|
||||
if (item.name.toLowerCase().indexOf(val.toLowerCase()) > -1) {
|
||||
result.push({ ...item })
|
||||
} else if (item.children) {
|
||||
const filterSearchData = searchData(val, item.children)
|
||||
if (filterSearchData.length) {
|
||||
result.push({
|
||||
...item,
|
||||
children: filterSearchData
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
const filterData = (tree: any[], ignoreIds: string[]) => {
|
||||
const traverse = (nodes: any) => {
|
||||
const result: any[] = []
|
||||
nodes.forEach((node: any) => {
|
||||
if (!ignoreIds.includes(node.id)) {
|
||||
const children = traverse(node.children)
|
||||
result.push({
|
||||
...node,
|
||||
children: children || []
|
||||
})
|
||||
}
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
return traverse(tree)
|
||||
}
|
||||
|
||||
export default (ignoreIds?: string[]) => {
|
||||
const searchKey = ref('')
|
||||
|
||||
const treeData = ref([])
|
||||
const searchTreeData = computed(() => searchData(searchKey.value, treeData.value))
|
||||
const realTreeData = computed(() => filterData(searchTreeData.value, ignoreIds || []))
|
||||
|
||||
let timeout: any
|
||||
const inputChange = (val: string) => {
|
||||
if (timeout) clearTimeout(timeout)
|
||||
timeout = setTimeout(() => {
|
||||
searchKey.value = val
|
||||
}, 300)
|
||||
}
|
||||
return {
|
||||
searchKey,
|
||||
treeData,
|
||||
realTreeData,
|
||||
inputChange
|
||||
}
|
||||
}
|
36
src/components/f-dept-tree/f-dept-tree-item-node.vue
Normal file
36
src/components/f-dept-tree/f-dept-tree-item-node.vue
Normal file
@ -0,0 +1,36 @@
|
||||
<template>
|
||||
<template v-if="index < 0">{{ nodeTitleArr[0] }}</template>
|
||||
<span v-else>
|
||||
{{ nodeTitleArr[0]
|
||||
}}<span style="color: rgb(var(--primary-5)); font-weight: bold"> {{ nodeTitleArr[1] }}</span
|
||||
>{{ nodeTitleArr[2] }}
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
|
||||
const props = defineProps<{
|
||||
searchKey: string
|
||||
itemData: any
|
||||
titleField: string
|
||||
}>()
|
||||
|
||||
const getMatchIndex = (title: string) => {
|
||||
if (!props.searchKey) return -1
|
||||
return title.toLowerCase().indexOf(props.searchKey.toLowerCase())
|
||||
}
|
||||
const index = computed(() => getMatchIndex(props.itemData[props.titleField || 'title']))
|
||||
|
||||
const nodeTitleArr = computed<string[]>(() => {
|
||||
const title: string = props.itemData[props.titleField || 'title'] || ''
|
||||
if (index.value < 0) {
|
||||
return [title]
|
||||
}
|
||||
return [
|
||||
title.substring(0, index.value),
|
||||
title.substring(index.value, index.value + props.searchKey.length),
|
||||
title.substring(index.value + props.searchKey.length)
|
||||
]
|
||||
})
|
||||
</script>
|
126
src/components/f-dept-tree/index.vue
Normal file
126
src/components/f-dept-tree/index.vue
Normal file
@ -0,0 +1,126 @@
|
||||
<template>
|
||||
<a-skeleton :animation="true" :loading="loading">
|
||||
<a-card>
|
||||
<a-skeleton-line :rows="8" />
|
||||
</a-card>
|
||||
|
||||
<template #content>
|
||||
<a-card
|
||||
:body-style="{ minHeight: '100px', padding: '8px' }"
|
||||
:header-style="{ padding: '8px 3px 8px 8px' }"
|
||||
>
|
||||
<template #title>
|
||||
<div class="align-center flex-row">
|
||||
<a-input
|
||||
class="flex-1"
|
||||
:allow-clear="true"
|
||||
placeholder="搜索部门.."
|
||||
@input="inputChange"
|
||||
@clear="inputChange('')"
|
||||
><template #prefix> <icon-search /> </template
|
||||
></a-input>
|
||||
<a-tooltip content="仅展示部门的直属成员" :popup-visible="deptTooltipVisible">
|
||||
<template #content>
|
||||
仅展示部门的直属成员
|
||||
<a-tooltip content="不再提示">
|
||||
<icon-close style="cursor: pointer" @click="handleCloseDeptTooltip" />
|
||||
</a-tooltip>
|
||||
</template>
|
||||
<a-tooltip content="仅展示部门的直属成员">
|
||||
<a-checkbox
|
||||
style="padding-right: 5px"
|
||||
v-model="innerOnly"
|
||||
@change="handleCheckboxChange"
|
||||
></a-checkbox>
|
||||
</a-tooltip>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<a-empty v-if="realTreeData.length === 0" description="没有匹配的部门"></a-empty>
|
||||
<a-tree
|
||||
v-else
|
||||
:data="realTreeData"
|
||||
:field-names="fieldNames"
|
||||
:block-node="true"
|
||||
:default-expand-all="true"
|
||||
@select="handleTreeSelect"
|
||||
>
|
||||
<template #icon="{ node }">
|
||||
<div v-if="node.id === '0'" class="iconfont icon-enterprise dept-tree-icon"></div>
|
||||
<icon-user-group class="dept-tree-icon" v-else />
|
||||
</template>
|
||||
<template #title="nodeData">
|
||||
<item-node :item-data="nodeData" :search-key="searchKey" title-field="name"></item-node>
|
||||
</template>
|
||||
</a-tree>
|
||||
</a-card>
|
||||
</template>
|
||||
</a-skeleton>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { TreeFieldNames } from '@arco-design/web-vue'
|
||||
import { IconSearch, IconUserGroup, IconClose } from '@arco-design/web-vue/es/icon'
|
||||
import { ref } from 'vue'
|
||||
import { fetchAllTree } from '@/api/upms/dept'
|
||||
import useSearch from '../_hooks/use-tree-search'
|
||||
import useDeptTooltip from './use-dept-tooltip'
|
||||
import ItemNode from './f-dept-tree-item-node.vue'
|
||||
|
||||
const emit = defineEmits<{
|
||||
(event: 'change', val: { deptId?: string; innerOnly: boolean }): void
|
||||
}>()
|
||||
|
||||
const { deptTooltipVisible, handleCloseDeptTooltip } = useDeptTooltip()
|
||||
const { searchKey, treeData, realTreeData, inputChange } = useSearch()
|
||||
|
||||
const fieldNames: TreeFieldNames = {
|
||||
key: 'id',
|
||||
title: 'name'
|
||||
}
|
||||
|
||||
const loading = ref(true)
|
||||
|
||||
fetchAllTree().then((res) => {
|
||||
treeData.value = res
|
||||
loading.value = false
|
||||
})
|
||||
|
||||
const selectDeptId = ref<string | undefined>(undefined)
|
||||
const innerOnly = ref(false)
|
||||
const handleCheckboxChange = () => {
|
||||
emit('change', {
|
||||
deptId: selectDeptId.value,
|
||||
innerOnly: innerOnly.value
|
||||
})
|
||||
}
|
||||
|
||||
const handleTreeSelect = (keys: (string | number)[]) => {
|
||||
if (selectDeptId.value === keys[0]) {
|
||||
return
|
||||
}
|
||||
// eslint-disable-next-line prefer-destructuring
|
||||
selectDeptId.value = keys[0] as string
|
||||
emit('change', {
|
||||
deptId: selectDeptId.value,
|
||||
innerOnly: innerOnly.value
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.dept-tree-icon {
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
.arco-avatar {
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
::v-deep(.arco-tree-node-icon) {
|
||||
margin-right: 6px;
|
||||
}
|
||||
.arco-tree-node-selected {
|
||||
.dept-tree-icon {
|
||||
color: rgb(var(--primary-6));
|
||||
}
|
||||
}
|
||||
</style>
|
21
src/components/f-dept-tree/use-dept-tooltip.ts
Normal file
21
src/components/f-dept-tree/use-dept-tooltip.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import { ref } from 'vue'
|
||||
import { getStore, setStore } from '@/utils/storage'
|
||||
|
||||
export default () => {
|
||||
const deptTooltipVisible = ref(false)
|
||||
if (getStore('dept_tooltip_visible') !== true) {
|
||||
setTimeout(() => {
|
||||
deptTooltipVisible.value = true
|
||||
setTimeout(() => {
|
||||
deptTooltipVisible.value = false
|
||||
}, 3000)
|
||||
}, 1000)
|
||||
}
|
||||
const handleCloseDeptTooltip = () => {
|
||||
setStore('dept_tooltip_visible', true)
|
||||
}
|
||||
return {
|
||||
deptTooltipVisible,
|
||||
handleCloseDeptTooltip
|
||||
}
|
||||
}
|
41
src/components/f-user-avatar/index.vue
Normal file
41
src/components/f-user-avatar/index.vue
Normal file
@ -0,0 +1,41 @@
|
||||
<template>
|
||||
<a-avatar :customClass="customClass" :shape="shape" :size="size" v-if="src">
|
||||
<img alt="avatar" :src="src" />
|
||||
</a-avatar>
|
||||
<a-avatar :customClass="customClass" :shape="shape" :size="size" v-else-if="text">
|
||||
{{ showText }}
|
||||
</a-avatar>
|
||||
<a-avatar :customClass="customClass" :shape="shape" :size="size" v-else>
|
||||
<IconUser />
|
||||
</a-avatar>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, withDefaults } from 'vue'
|
||||
import { IconUser } from '@arco-design/web-vue/es/icon'
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
customClass?: string
|
||||
shape?: 'circle' | 'square'
|
||||
size?: number
|
||||
text?: string
|
||||
firstText?: boolean
|
||||
src?: string
|
||||
}>(),
|
||||
{
|
||||
shape: 'square',
|
||||
text: '',
|
||||
firstText: true,
|
||||
size: 20
|
||||
}
|
||||
)
|
||||
const showText = computed(() => {
|
||||
if (!props.text) {
|
||||
return ''
|
||||
}
|
||||
return props.firstText ? props.text.substring(0, 1) : props.text
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
@ -0,0 +1,36 @@
|
||||
<template>
|
||||
<span v-if="index < 0" class="select-none">{{ nodeTitleArr[0] }}</span>
|
||||
<span v-else class="select-none">
|
||||
{{ nodeTitleArr[0]
|
||||
}}<span style="color: rgb(var(--primary-5)); font-weight: bold"> {{ nodeTitleArr[1] }}</span
|
||||
>{{ nodeTitleArr[2] }}
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
|
||||
const props = defineProps<{
|
||||
searchKey: string
|
||||
itemData: any
|
||||
titleField: string
|
||||
}>()
|
||||
|
||||
const getMatchIndex = (title: string) => {
|
||||
if (!props.searchKey) return -1
|
||||
return title.toLowerCase().indexOf(props.searchKey.toLowerCase())
|
||||
}
|
||||
const index = computed(() => getMatchIndex(props.itemData[props.titleField || 'title']))
|
||||
|
||||
const nodeTitleArr = computed<string[]>(() => {
|
||||
const title: string = props.itemData[props.titleField || 'title'] || ''
|
||||
if (index.value < 0) {
|
||||
return [title]
|
||||
}
|
||||
return [
|
||||
title.substring(0, index.value),
|
||||
title.substring(index.value, index.value + props.searchKey.length),
|
||||
title.substring(index.value + props.searchKey.length)
|
||||
]
|
||||
})
|
||||
</script>
|
270
src/components/f-user-select-modal/index.vue
Normal file
270
src/components/f-user-select-modal/index.vue
Normal file
@ -0,0 +1,270 @@
|
||||
<template>
|
||||
<a-modal
|
||||
v-model:visible="myVisible"
|
||||
title="选择成员"
|
||||
:unmount-on-close="true"
|
||||
:footer="false"
|
||||
:width="width"
|
||||
:mask-closable="false"
|
||||
modal-class="user-select-modal"
|
||||
>
|
||||
<div class="user-select-modal-body flex-row">
|
||||
<div class="tree-box flex-1">
|
||||
<div class="search-box">
|
||||
<a-input
|
||||
:allow-clear="true"
|
||||
placeholder="搜索"
|
||||
@input="inputChange"
|
||||
@clear="inputChange('')"
|
||||
>
|
||||
<template #prefix>
|
||||
<icon-search />
|
||||
</template>
|
||||
</a-input>
|
||||
</div>
|
||||
<div
|
||||
v-if="realTreeData.length === 0"
|
||||
:style="{ height: `${height - 20}px` }"
|
||||
class="justify-center"
|
||||
>
|
||||
<a-empty description="没有匹配的部门/成员"></a-empty>
|
||||
</div>
|
||||
<a-tree
|
||||
v-else
|
||||
:checked-keys="checkedKeys"
|
||||
:checkable="checkedKeys.length < limit"
|
||||
:data="realTreeData"
|
||||
:field-names="{
|
||||
key: 'id',
|
||||
title: 'name'
|
||||
}"
|
||||
:block-node="true"
|
||||
:default-expand-all="true"
|
||||
:virtual-list-props="{
|
||||
height: `${height - 20}px`,
|
||||
fixedSize: true,
|
||||
buffer: 30
|
||||
}"
|
||||
:disabled="checkedKeys.length === limit"
|
||||
@check="handleCheck"
|
||||
@select="handleSelect"
|
||||
>
|
||||
<template #icon="{ node }">
|
||||
<div v-if="node.id === '0'" class="iconfont icon-enterprise dept-tree-icon"></div>
|
||||
<f-user-avatar
|
||||
v-else-if="node.type === 'user'"
|
||||
custom-class="dept-tree-icon"
|
||||
:text="node.name"
|
||||
:src="node.avatarUrl"
|
||||
></f-user-avatar>
|
||||
<icon-user-group class="dept-tree-icon" v-else />
|
||||
</template>
|
||||
<template #title="nodeData">
|
||||
<item-node :item-data="nodeData" :search-key="searchKey" title-field="name"></item-node>
|
||||
</template>
|
||||
</a-tree>
|
||||
</div>
|
||||
<div class="list-box flex-1">
|
||||
<div>
|
||||
<div style="margin-bottom: 10px">
|
||||
<a-typography-text>
|
||||
{{
|
||||
checkedKeys.length === 0
|
||||
? '请从左侧选择成员'
|
||||
: `已选择了${checkedKeys.length}位成员`
|
||||
}}{{ checkedKeys.length === limit ? `,` : '' }} </a-typography-text
|
||||
><a-typography-text type="danger">
|
||||
{{ checkedKeys.length === limit ? `最多选择${limit}位` : '' }}
|
||||
</a-typography-text>
|
||||
</div>
|
||||
<a-scrollbar
|
||||
style="overflow-y: auto; padding-right: 20px"
|
||||
:style="{ height: `${height - 54}px` }"
|
||||
>
|
||||
<div
|
||||
v-for="node in checkedNodes"
|
||||
:key="node.id"
|
||||
class="align-center flex-row justify-between"
|
||||
style="padding: 6px 0"
|
||||
>
|
||||
<div class="align-center flex-row">
|
||||
<a-avatar style="margin-right: 10px" shape="square" :size="20"
|
||||
>{{ node.name.substring(0, 1) }}
|
||||
</a-avatar>
|
||||
<a-typography-text>{{ node.name }}</a-typography-text>
|
||||
</div>
|
||||
<div style="padding: 0 4px; cursor: pointer" @click="handleUncheck(node)">
|
||||
<icon-close-circle-fill />
|
||||
</div>
|
||||
</div>
|
||||
</a-scrollbar>
|
||||
<div class="flex-row justify-end" style="padding-right: 20px; margin-top: 10px">
|
||||
<a-space>
|
||||
<a-button @click="handleCancel">取消</a-button>
|
||||
<c-button type="primary" @click="handleSubmit">确定</c-button>
|
||||
</a-space>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a-modal>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed, nextTick, ref, watch, watchEffect, withDefaults } from 'vue'
|
||||
import { IconCloseCircleFill, IconUserGroup } from '@arco-design/web-vue/es/icon'
|
||||
import _ from 'lodash'
|
||||
import useSearch from '../_hooks/use-tree-search'
|
||||
import { fetchUserTree } from '@/api/upms/dept'
|
||||
import useCheck from './use-check'
|
||||
import useAdaptSize from '@/components/f-user-select-modal/use-adapt-size'
|
||||
import FUserAvatar from '../f-user-avatar/index.vue'
|
||||
import { searchUserList } from './use-search'
|
||||
import ItemNode from './f-user-select-modal-item-node.vue'
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
visible: boolean
|
||||
limit?: number
|
||||
selectIds?: string[]
|
||||
/**
|
||||
* 忽略的ids
|
||||
*/
|
||||
ignoreIds?: string[]
|
||||
autoClose?: boolean
|
||||
}>(),
|
||||
{
|
||||
limit: 99,
|
||||
selectIds: () => [],
|
||||
ignoreIds: () => [],
|
||||
autoClose: true
|
||||
}
|
||||
)
|
||||
const emit = defineEmits<{
|
||||
(event: 'update:visible', val: boolean): void
|
||||
(event: 'userListChange', val: any[]): void
|
||||
(event: 'change', checkKeys: string[], checkNodes: any[]): void
|
||||
(event: 'change', checkKeys: string[], checkNodes: any[], done: Function): void
|
||||
}>()
|
||||
// search
|
||||
const { searchKey, treeData, realTreeData, inputChange } = useSearch(props.ignoreIds)
|
||||
const userListData = computed(() => searchUserList(treeData.value))
|
||||
// check
|
||||
const { handleSelect, handleCheck, handleUncheck, synchronize, checkedKeys, checkedNodes } =
|
||||
useCheck(treeData, props.limit)
|
||||
// load data
|
||||
const load = () => {
|
||||
fetchUserTree().then((res) => {
|
||||
treeData.value = res
|
||||
nextTick(() => {
|
||||
emit('userListChange', userListData.value)
|
||||
})
|
||||
synchronize()
|
||||
})
|
||||
}
|
||||
load()
|
||||
// v-model:select-ids
|
||||
watch(
|
||||
() => props.selectIds,
|
||||
() => {
|
||||
checkedKeys.value = _.cloneDeep(props.selectIds)
|
||||
synchronize()
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
deep: true
|
||||
}
|
||||
)
|
||||
// cal height
|
||||
const { width, height } = useAdaptSize()
|
||||
|
||||
// modal visible
|
||||
const myVisible = ref(false)
|
||||
const backSelectIds = ref<string[]>([])
|
||||
watchEffect(() => {
|
||||
emit('update:visible', myVisible.value)
|
||||
})
|
||||
watch(
|
||||
() => props.visible,
|
||||
() => {
|
||||
myVisible.value = props.visible
|
||||
// 打开对话框记录下此时选择的ids
|
||||
if (myVisible.value) {
|
||||
backSelectIds.value = _.cloneDeep(checkedKeys.value)
|
||||
}
|
||||
searchKey.value = ''
|
||||
}
|
||||
)
|
||||
// operation
|
||||
const handleCancel = () => {
|
||||
myVisible.value = false
|
||||
// 如果点击了取消,重置为之前选择的ids
|
||||
checkedKeys.value = backSelectIds.value
|
||||
synchronize()
|
||||
}
|
||||
const handleSubmit = (done: Function) => {
|
||||
emit('change', _.cloneDeep(checkedKeys.value), _.cloneDeep(checkedNodes.value), (flag: any) => {
|
||||
if (flag !== false) {
|
||||
myVisible.value = false
|
||||
load()
|
||||
}
|
||||
done()
|
||||
})
|
||||
if (props.autoClose) {
|
||||
myVisible.value = false
|
||||
done()
|
||||
load()
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
load
|
||||
})
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.user-select-modal {
|
||||
.arco-modal-header {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.arco-modal-body {
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
max-height: 100vh;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.tree-box,
|
||||
.list-box {
|
||||
padding: 20px 0 20px 20px;
|
||||
}
|
||||
|
||||
.tree-box {
|
||||
border-right: 1px solid var(--color-neutral-3);
|
||||
|
||||
.search-box {
|
||||
padding-right: 20px;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.user-select-modal-body {
|
||||
.arco-virtual-list {
|
||||
overflow-x: hidden !important;
|
||||
}
|
||||
.arco-tree-node-selected {
|
||||
// .arco-avatar {
|
||||
// background-color: rgb(var(--primary-5));
|
||||
// }
|
||||
.arco-tree-node-title {
|
||||
color: var(--color-text-1);
|
||||
}
|
||||
}
|
||||
.arco-card-body {
|
||||
padding: 0;
|
||||
}
|
||||
.arco-tree-node-title-text {
|
||||
min-width: 80px;
|
||||
}
|
||||
}
|
||||
</style>
|
44
src/components/f-user-select-modal/use-adapt-size.ts
Normal file
44
src/components/f-user-select-modal/use-adapt-size.ts
Normal file
@ -0,0 +1,44 @@
|
||||
import { inject, computed, Ref } from 'vue'
|
||||
import { isUndefined } from 'lodash'
|
||||
import { SystemInfo } from '@/types/types'
|
||||
|
||||
export default () => {
|
||||
const systemInfo = inject<Ref<SystemInfo>>('systemInfo')
|
||||
const height = computed(() => {
|
||||
if (isUndefined(systemInfo)) {
|
||||
return 100
|
||||
}
|
||||
if (systemInfo.value.clientHeight > 1000) {
|
||||
return 900
|
||||
}
|
||||
if (systemInfo.value.clientHeight > 800) {
|
||||
return 600
|
||||
}
|
||||
if (systemInfo.value.clientHeight > 600) {
|
||||
return 440
|
||||
}
|
||||
if (systemInfo.value.clientHeight > 500) {
|
||||
return 440
|
||||
}
|
||||
return systemInfo.value.clientHeight - 60
|
||||
})
|
||||
const width = computed(() => {
|
||||
if (!systemInfo) {
|
||||
return '520px'
|
||||
}
|
||||
if (systemInfo.value.clientWidth > 1920) {
|
||||
return '720px'
|
||||
}
|
||||
if (systemInfo.value.clientWidth > 1360) {
|
||||
return '620px'
|
||||
}
|
||||
if (systemInfo.value.clientWidth < 600) {
|
||||
return `${systemInfo.value.clientWidth}px`
|
||||
}
|
||||
return '520px'
|
||||
})
|
||||
return {
|
||||
width,
|
||||
height
|
||||
}
|
||||
}
|
115
src/components/f-user-select-modal/use-check.ts
Normal file
115
src/components/f-user-select-modal/use-check.ts
Normal file
@ -0,0 +1,115 @@
|
||||
import { TreeNodeData } from '@arco-design/web-vue'
|
||||
import { Ref, ref } from 'vue'
|
||||
import _, { isUndefined } from 'lodash'
|
||||
/**
|
||||
* 根据ids搜索出nodes
|
||||
*
|
||||
* @param ids 选中的ids
|
||||
* @param tree 树所有节点数据
|
||||
*/
|
||||
const searchTree = (ids: string[], tree: any[]): any[] => {
|
||||
const finds: any[] = []
|
||||
if (tree) {
|
||||
tree.forEach((node) => {
|
||||
if (node) {
|
||||
if (ids.findIndex((id) => id === node.id) >= 0) {
|
||||
finds.push(node)
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const findChild = searchTree(ids, node.children)
|
||||
finds.push(...findChild)
|
||||
}
|
||||
})
|
||||
}
|
||||
return _.unionWith(finds, (arrVal, othVal) => {
|
||||
return arrVal.id === othVal.id
|
||||
})
|
||||
}
|
||||
export default (treeData: Ref<any[]>, limit: number) => {
|
||||
/**
|
||||
* 选中的ids
|
||||
*/
|
||||
const checkedKeys = ref<string[]>([])
|
||||
/**
|
||||
* 选中的nodes
|
||||
*/
|
||||
const checkedNodes = ref<any[]>([])
|
||||
const canCheck = computed(() => limit > checkedKeys.value.length)
|
||||
/**
|
||||
* 计算checkedKeys和checkedNodes
|
||||
* @param node 节点数据{id,name,...}
|
||||
*/
|
||||
const checkChange = (node?: any) => {
|
||||
if (!isUndefined(node)) {
|
||||
const idx = checkedKeys.value.findIndex((item) => item === node.id)
|
||||
if (idx >= 0) {
|
||||
checkedKeys.value.splice(idx, 1)
|
||||
checkedNodes.value.splice(idx, 1)
|
||||
} else {
|
||||
if (!canCheck.value) {
|
||||
checkedKeys.value.splice(checkedKeys.value.length - 1, 1)
|
||||
checkedNodes.value.splice(checkedNodes.value.length - 1, 1)
|
||||
}
|
||||
checkedKeys.value.push(node.id)
|
||||
checkedNodes.value.push(node)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 提供给a-tree的@select事件
|
||||
* @param keys 选择的keys,string[]
|
||||
* @param data 反馈数据
|
||||
*/
|
||||
const handleSelect = (
|
||||
keys: (string | number)[],
|
||||
data: { selected?: boolean; selectedNodes: TreeNodeData[]; node?: TreeNodeData; e?: Event }
|
||||
) => {
|
||||
if (data.node && data.node.checkable) {
|
||||
checkChange(data.node)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 提供给a-tree的@check事件
|
||||
* @param keys 选择的keys,string[]
|
||||
* @param data 反馈数据
|
||||
*/
|
||||
const handleCheck = (
|
||||
keys: Array<string | number>,
|
||||
data: {
|
||||
checked?: boolean
|
||||
checkedNodes: TreeNodeData[]
|
||||
node?: TreeNodeData
|
||||
e?: Event
|
||||
halfCheckedKeys: (string | number)[]
|
||||
halfCheckedNodes: TreeNodeData[]
|
||||
}
|
||||
) => {
|
||||
if (data.node && data.node.checkable) {
|
||||
checkChange(data.node)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消选择
|
||||
* @param node 节点数据{id,name,...}
|
||||
*/
|
||||
const handleUncheck = (node: any) => {
|
||||
checkChange(node)
|
||||
}
|
||||
/**
|
||||
* 让checkedNodes根据checkedKeys同步数据
|
||||
*/
|
||||
const synchronize = () => {
|
||||
checkedNodes.value = searchTree(checkedKeys.value, treeData.value)
|
||||
}
|
||||
return {
|
||||
checkedKeys,
|
||||
checkedNodes,
|
||||
handleSelect,
|
||||
handleUncheck,
|
||||
handleCheck,
|
||||
synchronize
|
||||
}
|
||||
}
|
24
src/components/f-user-select-modal/use-search.ts
Normal file
24
src/components/f-user-select-modal/use-search.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import _ from 'lodash'
|
||||
/**
|
||||
* 从树结构过滤出用户list
|
||||
*
|
||||
* @param tree 树所有节点数据
|
||||
*/
|
||||
export const searchUserList = (tree: any[]): any[] => {
|
||||
const finds: any[] = []
|
||||
if (tree) {
|
||||
tree.forEach((node) => {
|
||||
if (node) {
|
||||
if (node.type === 'user') {
|
||||
finds.push(node)
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const findChild = searchUserList(node.children)
|
||||
finds.push(...findChild)
|
||||
}
|
||||
})
|
||||
}
|
||||
return _.unionWith(finds, (arrVal, othVal) => {
|
||||
return arrVal.id === othVal.id
|
||||
})
|
||||
}
|
93
src/components/f-user-select/index.vue
Normal file
93
src/components/f-user-select/index.vue
Normal file
@ -0,0 +1,93 @@
|
||||
<template>
|
||||
<a-select
|
||||
:popup-visible="false"
|
||||
:fallback-option="false"
|
||||
:multiple="limit === 1 ? false : true"
|
||||
:allow-search="false"
|
||||
:allow-clear="allowClear"
|
||||
:placeholder="placeholder"
|
||||
@popup-visible-change="handleVisible"
|
||||
@remove="handleRemove"
|
||||
@clear="handleRemove"
|
||||
v-model="mySelectIds"
|
||||
>
|
||||
<a-option v-for="item of options" :key="item.id" :value="item.id" :label="item.name" />
|
||||
</a-select>
|
||||
<f-user-select-modal
|
||||
v-model:visible="modalVisible"
|
||||
:select-ids="mySelectIds"
|
||||
:limit="limit"
|
||||
:ignoreIds="ignoreIds"
|
||||
@change="handleChange"
|
||||
@user-list-change="handleUserListChange"
|
||||
></f-user-select-modal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, watch, withDefaults } from 'vue'
|
||||
import _ from 'lodash'
|
||||
import FUserSelectModal from '../f-user-select-modal/index.vue'
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
/**
|
||||
* 已选择
|
||||
*/
|
||||
selectIds?: string[]
|
||||
/**
|
||||
* 忽略的ids
|
||||
*/
|
||||
ignoreIds?: string[]
|
||||
/**
|
||||
* 最多可选几个
|
||||
*/
|
||||
limit?: number
|
||||
|
||||
allowClear?: boolean
|
||||
placeholder?: string
|
||||
}>(),
|
||||
{
|
||||
allowClear: true,
|
||||
selectIds: () => [],
|
||||
ignoreIds: () => [],
|
||||
placeholder: '请选择人员'
|
||||
}
|
||||
)
|
||||
const emit = defineEmits<{
|
||||
(event: 'change', val: string[]): void
|
||||
}>()
|
||||
|
||||
const modalVisible = ref(false)
|
||||
const handleVisible = () => {
|
||||
modalVisible.value = true
|
||||
}
|
||||
|
||||
const mySelectIds = ref<string[]>([])
|
||||
watch(
|
||||
() => props.selectIds,
|
||||
() => {
|
||||
mySelectIds.value = _.cloneDeep(props.selectIds || [])
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
immediate: true
|
||||
}
|
||||
)
|
||||
|
||||
const options = ref<any[]>([])
|
||||
const handleChange = (ids: string[], nodes: any[]) => {
|
||||
options.value = nodes
|
||||
mySelectIds.value = ids
|
||||
emit('change', ids)
|
||||
}
|
||||
|
||||
const handleRemove = () => {
|
||||
emit('change', mySelectIds.value)
|
||||
}
|
||||
|
||||
const handleUserListChange = (list: any[]) => {
|
||||
options.value = list
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
32
src/components/f-user-select/option.ts
Normal file
32
src/components/f-user-select/option.ts
Normal file
@ -0,0 +1,32 @@
|
||||
import { TableOption } from '@/types'
|
||||
|
||||
const option: TableOption = {
|
||||
api: {
|
||||
base: '/sys/user',
|
||||
page: '/page/res'
|
||||
},
|
||||
addBtn: false,
|
||||
editBtn: false,
|
||||
delBtn: false,
|
||||
menuProps: {
|
||||
display: false
|
||||
},
|
||||
rowSelection: {},
|
||||
columns: [
|
||||
{
|
||||
name: '姓名',
|
||||
prop: 'fullName'
|
||||
},
|
||||
{
|
||||
name: '手机号',
|
||||
prop: 'phone'
|
||||
},
|
||||
{
|
||||
name: '部门',
|
||||
prop: 'deptNames',
|
||||
addDisplay: false,
|
||||
editDisplay: false
|
||||
}
|
||||
]
|
||||
}
|
||||
export default option
|
439
src/components/verifition/Verify.vue
Normal file
439
src/components/verifition/Verify.vue
Normal file
File diff suppressed because one or more lines are too long
291
src/components/verifition/Verify/VerifyPoints.vue
Normal file
291
src/components/verifition/Verify/VerifyPoints.vue
Normal file
@ -0,0 +1,291 @@
|
||||
<template>
|
||||
<div style="position: relative">
|
||||
<div class="verify-img-out">
|
||||
<div
|
||||
class="verify-img-panel"
|
||||
:style="{
|
||||
width: setSize.imgWidth,
|
||||
height: setSize.imgHeight,
|
||||
'background-size': setSize.imgWidth + ' ' + setSize.imgHeight,
|
||||
'margin-bottom': vSpace + 'px'
|
||||
}"
|
||||
>
|
||||
<div class="verify-refresh" style="z-index: 3" @click="refresh" v-show="showRefresh">
|
||||
<i class="iconfont icon-refresh"></i>
|
||||
</div>
|
||||
<img
|
||||
:src="'data:image/png;base64,' + pointBackImgBase"
|
||||
ref="canvas"
|
||||
alt=""
|
||||
style="width: 100%; height: 100%; display: block"
|
||||
@click="bindingClick ? canvasClick($event) : undefined"
|
||||
/>
|
||||
|
||||
<div
|
||||
v-for="(tempPoint, index) in tempPoints"
|
||||
:key="index"
|
||||
class="point-area"
|
||||
:style="{
|
||||
'background-color': '#1abd6c',
|
||||
color: '#fff',
|
||||
'z-index': 9999,
|
||||
width: '20px',
|
||||
height: '20px',
|
||||
'text-align': 'center',
|
||||
'line-height': '20px',
|
||||
'border-radius': '50%',
|
||||
position: 'absolute',
|
||||
top: parseInt(tempPoint.y - 10) + 'px',
|
||||
left: parseInt(tempPoint.x - 10) + 'px'
|
||||
}"
|
||||
>
|
||||
{{ index + 1 }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 'height': this.barSize.height, -->
|
||||
<div
|
||||
class="verify-bar-area"
|
||||
:style="{
|
||||
width: setSize.imgWidth,
|
||||
color: this.barAreaColor,
|
||||
'border-color': this.barAreaBorderColor,
|
||||
'line-height': this.barSize.height
|
||||
}"
|
||||
>
|
||||
<span class="verify-msg">{{ text }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script type="text/babel">
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* VerifyPoints
|
||||
* @description 点选
|
||||
* */
|
||||
import {
|
||||
computed,
|
||||
onMounted,
|
||||
reactive,
|
||||
ref,
|
||||
watch,
|
||||
nextTick,
|
||||
toRefs,
|
||||
watchEffect,
|
||||
getCurrentInstance
|
||||
} from 'vue'
|
||||
import { resetSize, _code_chars, _code_color1, _code_color2 } from '../utils/util'
|
||||
import { aesEncrypt } from '../utils/ase'
|
||||
import { reqGet, reqCheck } from '../api/index'
|
||||
|
||||
export default {
|
||||
name: 'VerifyPoints',
|
||||
props: {
|
||||
// 弹出式pop,固定fixed
|
||||
mode: {
|
||||
type: String,
|
||||
default: 'fixed'
|
||||
},
|
||||
captchaType: {
|
||||
type: String
|
||||
},
|
||||
// 间隔
|
||||
vSpace: {
|
||||
type: Number,
|
||||
default: 5
|
||||
},
|
||||
imgSize: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {
|
||||
width: '310px',
|
||||
height: '155px'
|
||||
}
|
||||
}
|
||||
},
|
||||
barSize: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {
|
||||
width: '310px',
|
||||
height: '40px'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
setup(props, context) {
|
||||
const { mode, captchaType, vSpace, imgSize, barSize } = toRefs(props)
|
||||
const { proxy } = getCurrentInstance()
|
||||
const secretKey = ref('') // 后端返回的ase加密秘钥
|
||||
const checkNum = ref(3) // 默认需要点击的字数
|
||||
const fontPos = reactive([]) // 选中的坐标信息
|
||||
const checkPosArr = reactive([]) // 用户点击的坐标
|
||||
const num = ref(1) // 点击的记数
|
||||
const pointBackImgBase = ref('') // 后端获取到的背景图片
|
||||
const poinTextList = reactive([]) // 后端返回的点击字体顺序
|
||||
const backToken = ref('') // 后端返回的token值
|
||||
const setSize = reactive({
|
||||
imgHeight: 0,
|
||||
imgWidth: 0,
|
||||
barHeight: 0,
|
||||
barWidth: 0
|
||||
})
|
||||
const tempPoints = reactive([])
|
||||
const text = ref('')
|
||||
const barAreaColor = ref(undefined)
|
||||
const barAreaBorderColor = ref(undefined)
|
||||
const showRefresh = ref(true)
|
||||
const bindingClick = ref(true)
|
||||
|
||||
const init = () => {
|
||||
// 加载页面
|
||||
fontPos.splice(0, fontPos.length)
|
||||
checkPosArr.splice(0, checkPosArr.length)
|
||||
num.value = 1
|
||||
getPictrue()
|
||||
nextTick(() => {
|
||||
const { imgHeight, imgWidth, barHeight, barWidth } = resetSize(proxy)
|
||||
setSize.imgHeight = imgHeight
|
||||
setSize.imgWidth = imgWidth
|
||||
setSize.barHeight = barHeight
|
||||
setSize.barWidth = barWidth
|
||||
proxy.$parent.$emit('ready', proxy)
|
||||
})
|
||||
}
|
||||
onMounted(() => {
|
||||
// 禁止拖拽
|
||||
init()
|
||||
proxy.$el.onselectstart = function () {
|
||||
return false
|
||||
}
|
||||
})
|
||||
const canvas = ref(null)
|
||||
const canvasClick = (e) => {
|
||||
checkPosArr.push(getMousePos(canvas, e))
|
||||
if (num.value == checkNum.value) {
|
||||
num.value = createPoint(getMousePos(canvas, e))
|
||||
// 按比例转换坐标值
|
||||
const arr = pointTransfrom(checkPosArr, setSize)
|
||||
checkPosArr.length = 0
|
||||
checkPosArr.push(...arr)
|
||||
// 等创建坐标执行完
|
||||
setTimeout(() => {
|
||||
// var flag = this.comparePos(this.fontPos, this.checkPosArr);
|
||||
// 发送后端请求
|
||||
const captchaVerification = secretKey.value
|
||||
? aesEncrypt(`${backToken.value}---${JSON.stringify(checkPosArr)}`, secretKey.value)
|
||||
: `${backToken.value}---${JSON.stringify(checkPosArr)}`
|
||||
const data = {
|
||||
captchaType: captchaType.value,
|
||||
pointJson: secretKey.value
|
||||
? aesEncrypt(JSON.stringify(checkPosArr), secretKey.value)
|
||||
: JSON.stringify(checkPosArr),
|
||||
token: backToken.value
|
||||
}
|
||||
reqCheck(data).then((res) => {
|
||||
if (res.repCode == '0000') {
|
||||
barAreaColor.value = '#4cae4c'
|
||||
barAreaBorderColor.value = '#5cb85c'
|
||||
text.value = '验证成功'
|
||||
bindingClick.value = false
|
||||
if (mode.value == 'pop') {
|
||||
setTimeout(() => {
|
||||
proxy.$parent.clickShow = false
|
||||
refresh()
|
||||
}, 800)
|
||||
}
|
||||
proxy.$parent.$emit('success', { captchaVerification })
|
||||
} else {
|
||||
proxy.$parent.$emit('error', proxy)
|
||||
barAreaColor.value = '#d9534f'
|
||||
barAreaBorderColor.value = '#d9534f'
|
||||
text.value = '验证失败'
|
||||
setTimeout(() => {
|
||||
refresh()
|
||||
}, 400)
|
||||
}
|
||||
})
|
||||
}, 400)
|
||||
}
|
||||
if (num.value < checkNum.value) {
|
||||
num.value = createPoint(getMousePos(canvas, e))
|
||||
}
|
||||
}
|
||||
// 获取坐标
|
||||
const getMousePos = function (obj, e) {
|
||||
const x = e.offsetX
|
||||
const y = e.offsetY
|
||||
return { x, y }
|
||||
}
|
||||
// 创建坐标点
|
||||
const createPoint = function (pos) {
|
||||
tempPoints.push({ ...pos })
|
||||
return num.value + 1
|
||||
}
|
||||
const refresh = function () {
|
||||
tempPoints.splice(0, tempPoints.length)
|
||||
barAreaColor.value = '#000'
|
||||
barAreaBorderColor.value = '#ddd'
|
||||
bindingClick.value = true
|
||||
fontPos.splice(0, fontPos.length)
|
||||
checkPosArr.splice(0, checkPosArr.length)
|
||||
num.value = 1
|
||||
getPictrue()
|
||||
text.value = '验证失败'
|
||||
showRefresh.value = true
|
||||
}
|
||||
|
||||
// 请求背景图片和验证图片
|
||||
function getPictrue() {
|
||||
const data = {
|
||||
captchaType: captchaType.value
|
||||
}
|
||||
reqGet(data).then((res) => {
|
||||
if (res.repCode == '0000') {
|
||||
pointBackImgBase.value = res.repData.originalImageBase64
|
||||
backToken.value = res.repData.token
|
||||
secretKey.value = res.repData.secretKey
|
||||
poinTextList.value = res.repData.wordList
|
||||
text.value = `请依次点击【${poinTextList.value.join(',')}】`
|
||||
} else {
|
||||
text.value = res.repMsg
|
||||
}
|
||||
})
|
||||
}
|
||||
// 坐标转换函数
|
||||
const pointTransfrom = function (pointArr, imgSize) {
|
||||
const newPointArr = pointArr.map((p) => {
|
||||
const x = Math.round((310 * p.x) / parseInt(imgSize.imgWidth))
|
||||
const y = Math.round((155 * p.y) / parseInt(imgSize.imgHeight))
|
||||
return { x, y }
|
||||
})
|
||||
return newPointArr
|
||||
}
|
||||
return {
|
||||
secretKey,
|
||||
checkNum,
|
||||
fontPos,
|
||||
checkPosArr,
|
||||
num,
|
||||
pointBackImgBase,
|
||||
poinTextList,
|
||||
backToken,
|
||||
setSize,
|
||||
tempPoints,
|
||||
text,
|
||||
barAreaColor,
|
||||
barAreaBorderColor,
|
||||
showRefresh,
|
||||
bindingClick,
|
||||
init,
|
||||
canvas,
|
||||
canvasClick,
|
||||
getMousePos,
|
||||
createPoint,
|
||||
refresh,
|
||||
getPictrue,
|
||||
pointTransfrom
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
423
src/components/verifition/Verify/VerifySlide.vue
Normal file
423
src/components/verifition/Verify/VerifySlide.vue
Normal file
@ -0,0 +1,423 @@
|
||||
<template>
|
||||
<div style="position: relative">
|
||||
<div
|
||||
v-if="type === '2'"
|
||||
class="verify-img-out"
|
||||
:style="{ height: parseInt(setSize.imgHeight) + vSpace + 'px' }"
|
||||
>
|
||||
<div class="verify-img-panel" :style="{ width: setSize.imgWidth, height: setSize.imgHeight }">
|
||||
<img
|
||||
:src="'data:image/png;base64,' + backImgBase"
|
||||
alt=""
|
||||
style="width: 100%; height: 100%; display: block; -webkit-user-drag: none"
|
||||
/>
|
||||
<div class="verify-refresh" @click="refresh" v-show="showRefresh">
|
||||
<i class="iconfont icon-refresh"></i>
|
||||
</div>
|
||||
<transition name="tips">
|
||||
<span class="verify-tips" v-if="tipWords" :class="passFlag ? 'suc-bg' : 'err-bg'">{{
|
||||
tipWords
|
||||
}}</span>
|
||||
</transition>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 公共部分 -->
|
||||
<div
|
||||
class="verify-bar-area"
|
||||
:style="{ width: setSize.imgWidth, height: barSize.height, 'line-height': barSize.height }"
|
||||
>
|
||||
<span class="verify-msg" v-text="text"></span>
|
||||
<div
|
||||
class="verify-left-bar"
|
||||
:style="{
|
||||
width: leftBarWidth !== undefined ? leftBarWidth : barSize.height,
|
||||
height: barSize.height,
|
||||
'border-color': leftBarBorderColor,
|
||||
transaction: transitionWidth
|
||||
}"
|
||||
>
|
||||
<span class="verify-msg" v-text="finishText"></span>
|
||||
<div
|
||||
class="verify-move-block"
|
||||
@touchstart="start"
|
||||
@mousedown="start"
|
||||
:style="{
|
||||
width: barSize.height,
|
||||
height: barSize.height,
|
||||
'background-color': moveBlockBackgroundColor,
|
||||
left: moveBlockLeft,
|
||||
transition: transitionLeft
|
||||
}"
|
||||
>
|
||||
<i :class="['verify-icon iconfont', iconClass]" :style="{ color: iconColor }"></i>
|
||||
<div
|
||||
v-if="type === '2'"
|
||||
class="verify-sub-block"
|
||||
:style="{
|
||||
width: Math.floor((parseInt(setSize.imgWidth) * 47) / 310) + 'px',
|
||||
height: setSize.imgHeight,
|
||||
top: '-' + (parseInt(setSize.imgHeight) + vSpace) + 'px',
|
||||
'background-size': setSize.imgWidth + ' ' + setSize.imgHeight
|
||||
}"
|
||||
>
|
||||
<img
|
||||
:src="'data:image/png;base64,' + blockBackImgBase"
|
||||
alt=""
|
||||
style="width: 100%; height: 100%; display: block; -webkit-user-drag: none"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script type="text/babel">
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* VerifySlide
|
||||
* @description 滑块
|
||||
* */
|
||||
import { aesEncrypt } from './../utils/ase'
|
||||
import { resetSize } from './../utils/util'
|
||||
import { reqGet, reqCheck } from './../api/index'
|
||||
import {
|
||||
computed,
|
||||
onMounted,
|
||||
reactive,
|
||||
ref,
|
||||
watch,
|
||||
nextTick,
|
||||
toRefs,
|
||||
watchEffect,
|
||||
getCurrentInstance
|
||||
} from 'vue'
|
||||
// "captchaType":"blockPuzzle",
|
||||
export default {
|
||||
name: 'VerifySlide',
|
||||
props: {
|
||||
captchaType: {
|
||||
type: String
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: '1'
|
||||
},
|
||||
//弹出式pop,固定fixed
|
||||
mode: {
|
||||
type: String,
|
||||
default: 'fixed'
|
||||
},
|
||||
vSpace: {
|
||||
type: Number,
|
||||
default: 5
|
||||
},
|
||||
explain: {
|
||||
type: String,
|
||||
default: '向右滑动完成验证'
|
||||
},
|
||||
imgSize: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {
|
||||
width: '310px',
|
||||
height: '155px'
|
||||
}
|
||||
}
|
||||
},
|
||||
blockSize: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {
|
||||
width: '50px',
|
||||
height: '50px'
|
||||
}
|
||||
}
|
||||
},
|
||||
barSize: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {
|
||||
width: '310px',
|
||||
height: '40px'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
setup(props, context) {
|
||||
const { mode, captchaType, vSpace, imgSize, barSize, type, blockSize, explain } = toRefs(props)
|
||||
const { proxy } = getCurrentInstance()
|
||||
let secretKey = ref(''), //后端返回的ase加密秘钥
|
||||
passFlag = ref(''), //是否通过的标识
|
||||
backImgBase = ref(''), //验证码背景图片
|
||||
blockBackImgBase = ref(''), //验证滑块的背景图片
|
||||
backToken = ref(''), //后端返回的唯一token值
|
||||
startMoveTime = ref(''), //移动开始的时间
|
||||
endMovetime = ref(''), //移动结束的时间
|
||||
tipsBackColor = ref(''), //提示词的背景颜色
|
||||
tipWords = ref(''),
|
||||
text = ref(''),
|
||||
finishText = ref(''),
|
||||
setSize = reactive({
|
||||
imgHeight: 0,
|
||||
imgWidth: 0,
|
||||
barHeight: 0,
|
||||
barWidth: 0
|
||||
}),
|
||||
top = ref(0),
|
||||
left = ref(0),
|
||||
moveBlockLeft = ref(undefined),
|
||||
leftBarWidth = ref(undefined),
|
||||
// 移动中样式
|
||||
moveBlockBackgroundColor = ref(undefined),
|
||||
leftBarBorderColor = ref('#ddd'),
|
||||
iconColor = ref(undefined),
|
||||
iconClass = ref('icon-right'),
|
||||
status = ref(false), //鼠标状态
|
||||
isEnd = ref(false), //是够验证完成
|
||||
showRefresh = ref(true),
|
||||
transitionLeft = ref(''),
|
||||
transitionWidth = ref(''),
|
||||
startLeft = ref(0)
|
||||
|
||||
const barArea = computed(() => {
|
||||
return proxy.$el.querySelector('.verify-bar-area')
|
||||
})
|
||||
function init() {
|
||||
text.value = explain.value
|
||||
getPictrue()
|
||||
nextTick(() => {
|
||||
let { imgHeight, imgWidth, barHeight, barWidth } = resetSize(proxy)
|
||||
setSize.imgHeight = imgHeight
|
||||
setSize.imgWidth = imgWidth
|
||||
setSize.barHeight = barHeight
|
||||
setSize.barWidth = barWidth
|
||||
proxy.$parent.$emit('ready', proxy)
|
||||
})
|
||||
|
||||
window.removeEventListener('touchmove', function (e) {
|
||||
move(e)
|
||||
})
|
||||
window.removeEventListener('mousemove', function (e) {
|
||||
move(e)
|
||||
})
|
||||
|
||||
//鼠标松开
|
||||
window.removeEventListener('touchend', function () {
|
||||
end()
|
||||
})
|
||||
window.removeEventListener('mouseup', function () {
|
||||
end()
|
||||
})
|
||||
|
||||
window.addEventListener('touchmove', function (e) {
|
||||
move(e)
|
||||
})
|
||||
window.addEventListener('mousemove', function (e) {
|
||||
move(e)
|
||||
})
|
||||
|
||||
//鼠标松开
|
||||
window.addEventListener('touchend', function () {
|
||||
end()
|
||||
})
|
||||
window.addEventListener('mouseup', function () {
|
||||
end()
|
||||
})
|
||||
}
|
||||
watch(type, () => {
|
||||
init()
|
||||
})
|
||||
onMounted(() => {
|
||||
// 禁止拖拽
|
||||
init()
|
||||
proxy.$el.onselectstart = function () {
|
||||
return false
|
||||
}
|
||||
})
|
||||
//鼠标按下
|
||||
function start(e) {
|
||||
e = e || window.event
|
||||
if (!e.touches) {
|
||||
//兼容PC端
|
||||
var x = e.clientX
|
||||
} else {
|
||||
//兼容移动端
|
||||
var x = e.touches[0].pageX
|
||||
}
|
||||
startLeft.value = Math.floor(x - barArea.value.getBoundingClientRect().left)
|
||||
startMoveTime.value = +new Date() //开始滑动的时间
|
||||
if (isEnd.value == false) {
|
||||
text.value = ''
|
||||
moveBlockBackgroundColor.value = '#337ab7'
|
||||
leftBarBorderColor.value = '#337AB7'
|
||||
iconColor.value = '#fff'
|
||||
e.stopPropagation()
|
||||
status.value = true
|
||||
}
|
||||
}
|
||||
//鼠标移动
|
||||
function move(e) {
|
||||
e = e || window.event
|
||||
if (status.value && isEnd.value == false) {
|
||||
if (!e.touches) {
|
||||
//兼容PC端
|
||||
var x = e.clientX
|
||||
} else {
|
||||
//兼容移动端
|
||||
var x = e.touches[0].pageX
|
||||
}
|
||||
var bar_area_left = barArea.value.getBoundingClientRect().left
|
||||
var move_block_left = x - bar_area_left //小方块相对于父元素的left值
|
||||
if (
|
||||
move_block_left >=
|
||||
barArea.value.offsetWidth - parseInt(parseInt(blockSize.value.width) / 2) - 2
|
||||
) {
|
||||
move_block_left =
|
||||
barArea.value.offsetWidth - parseInt(parseInt(blockSize.value.width) / 2) - 2
|
||||
}
|
||||
if (move_block_left <= 0) {
|
||||
move_block_left = parseInt(parseInt(blockSize.value.width) / 2)
|
||||
}
|
||||
//拖动后小方块的left值
|
||||
moveBlockLeft.value = move_block_left - startLeft.value + 'px'
|
||||
leftBarWidth.value = move_block_left - startLeft.value + 'px'
|
||||
}
|
||||
}
|
||||
|
||||
//鼠标松开
|
||||
function end() {
|
||||
endMovetime.value = +new Date()
|
||||
//判断是否重合
|
||||
if (status.value && isEnd.value == false) {
|
||||
var moveLeftDistance = parseInt((moveBlockLeft.value || '').replace('px', ''))
|
||||
moveLeftDistance = (moveLeftDistance * 310) / parseInt(setSize.imgWidth)
|
||||
let data = {
|
||||
captchaType: captchaType.value,
|
||||
pointJson: secretKey.value
|
||||
? aesEncrypt(JSON.stringify({ x: moveLeftDistance, y: 5.0 }), secretKey.value)
|
||||
: JSON.stringify({ x: moveLeftDistance, y: 5.0 }),
|
||||
token: backToken.value
|
||||
}
|
||||
reqCheck(data).then((res) => {
|
||||
if (res.repCode == '0000') {
|
||||
moveBlockBackgroundColor.value = '#5cb85c'
|
||||
leftBarBorderColor.value = '#5cb85c'
|
||||
iconColor.value = '#fff'
|
||||
iconClass.value = 'icon-check'
|
||||
showRefresh.value = false
|
||||
isEnd.value = true
|
||||
if (mode.value == 'pop') {
|
||||
setTimeout(() => {
|
||||
proxy.$parent.clickShow = false
|
||||
refresh()
|
||||
}, 1500)
|
||||
}
|
||||
passFlag.value = true
|
||||
tipWords.value = `${((endMovetime.value - startMoveTime.value) / 1000).toFixed(
|
||||
2
|
||||
)}s验证成功`
|
||||
var captchaVerification = secretKey.value
|
||||
? aesEncrypt(
|
||||
backToken.value + '---' + JSON.stringify({ x: moveLeftDistance, y: 5.0 }),
|
||||
secretKey.value
|
||||
)
|
||||
: backToken.value + '---' + JSON.stringify({ x: moveLeftDistance, y: 5.0 })
|
||||
setTimeout(() => {
|
||||
tipWords.value = ''
|
||||
proxy.$parent.closeBox()
|
||||
proxy.$parent.$emit('success', { captchaVerification })
|
||||
}, 1000)
|
||||
} else {
|
||||
moveBlockBackgroundColor.value = '#d9534f'
|
||||
leftBarBorderColor.value = '#d9534f'
|
||||
iconColor.value = '#fff'
|
||||
iconClass.value = 'icon-close'
|
||||
passFlag.value = false
|
||||
setTimeout(function () {
|
||||
refresh()
|
||||
}, 1000)
|
||||
proxy.$parent.$emit('error', proxy)
|
||||
tipWords.value = '验证失败'
|
||||
setTimeout(() => {
|
||||
tipWords.value = ''
|
||||
}, 1000)
|
||||
}
|
||||
})
|
||||
status.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const refresh = () => {
|
||||
showRefresh.value = true
|
||||
finishText.value = ''
|
||||
|
||||
transitionLeft.value = 'left .3s'
|
||||
moveBlockLeft.value = 0
|
||||
|
||||
leftBarWidth.value = undefined
|
||||
transitionWidth.value = 'width .3s'
|
||||
|
||||
leftBarBorderColor.value = '#ddd'
|
||||
moveBlockBackgroundColor.value = '#fff'
|
||||
iconColor.value = '#000'
|
||||
iconClass.value = 'icon-right'
|
||||
isEnd.value = false
|
||||
|
||||
getPictrue()
|
||||
setTimeout(() => {
|
||||
transitionWidth.value = ''
|
||||
transitionLeft.value = ''
|
||||
text.value = explain.value
|
||||
}, 300)
|
||||
}
|
||||
|
||||
// 请求背景图片和验证图片
|
||||
function getPictrue() {
|
||||
let data = {
|
||||
captchaType: captchaType.value
|
||||
}
|
||||
reqGet(data).then((res) => {
|
||||
if (res.repCode == '0000') {
|
||||
backImgBase.value = res.repData.originalImageBase64
|
||||
blockBackImgBase.value = res.repData.jigsawImageBase64
|
||||
backToken.value = res.repData.token
|
||||
secretKey.value = res.repData.secretKey
|
||||
} else {
|
||||
tipWords.value = res.repMsg
|
||||
}
|
||||
})
|
||||
}
|
||||
return {
|
||||
secretKey, //后端返回的ase加密秘钥
|
||||
passFlag, //是否通过的标识
|
||||
backImgBase, //验证码背景图片
|
||||
blockBackImgBase, //验证滑块的背景图片
|
||||
backToken, //后端返回的唯一token值
|
||||
startMoveTime, //移动开始的时间
|
||||
endMovetime, //移动结束的时间
|
||||
tipsBackColor, //提示词的背景颜色
|
||||
tipWords,
|
||||
text,
|
||||
finishText,
|
||||
setSize,
|
||||
top,
|
||||
left,
|
||||
moveBlockLeft,
|
||||
leftBarWidth,
|
||||
// 移动中样式
|
||||
moveBlockBackgroundColor,
|
||||
leftBarBorderColor,
|
||||
iconColor,
|
||||
iconClass,
|
||||
status, //鼠标状态
|
||||
isEnd, //是够验证完成
|
||||
showRefresh,
|
||||
transitionLeft,
|
||||
transitionWidth,
|
||||
barArea,
|
||||
refresh,
|
||||
start
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
23
src/components/verifition/api/index.js
Normal file
23
src/components/verifition/api/index.js
Normal file
@ -0,0 +1,23 @@
|
||||
/**
|
||||
* 此处可直接引用自己项目封装好的 axios 配合后端联调
|
||||
*/
|
||||
|
||||
import request from '@/utils/axios' // 组件内部封装的axios
|
||||
|
||||
// 获取验证图片 以及token
|
||||
export function reqGet(data) {
|
||||
return request({
|
||||
url: '/captcha/get',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 滑动或者点选验证
|
||||
export function reqCheck(data) {
|
||||
return request({
|
||||
url: '/captcha/check',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
15
src/components/verifition/utils/ase.js
Normal file
15
src/components/verifition/utils/ase.js
Normal file
@ -0,0 +1,15 @@
|
||||
import CryptoJS from 'crypto-js'
|
||||
/**
|
||||
* @word 要加密的内容
|
||||
* @keyWord String 服务器随机返回的关键字
|
||||
* */
|
||||
// eslint-disable-next-line import/prefer-default-export
|
||||
export function aesEncrypt(word, keyWord = 'XwKsGlMcdPMEhR1B') {
|
||||
const key = CryptoJS.enc.Utf8.parse(keyWord)
|
||||
const srcs = CryptoJS.enc.Utf8.parse(word)
|
||||
const encrypted = CryptoJS.AES.encrypt(srcs, key, {
|
||||
mode: CryptoJS.mode.ECB,
|
||||
padding: CryptoJS.pad.Pkcs7
|
||||
})
|
||||
return encrypted.toString()
|
||||
}
|
101
src/components/verifition/utils/util.js
Normal file
101
src/components/verifition/utils/util.js
Normal file
@ -0,0 +1,101 @@
|
||||
/* eslint-disable */
|
||||
export function resetSize(vm) {
|
||||
let img_width
|
||||
let img_height
|
||||
let bar_width
|
||||
let bar_height // 图片的宽度、高度,移动条的宽度、高度
|
||||
|
||||
const parentWidth = vm.$el.parentNode.offsetWidth || window.offsetWidth
|
||||
const parentHeight = vm.$el.parentNode.offsetHeight || window.offsetHeight
|
||||
if (vm.imgSize.width.indexOf('%') != -1) {
|
||||
img_width = `${(parseInt(vm.imgSize.width) / 100) * parentWidth}px`
|
||||
} else {
|
||||
img_width = vm.imgSize.width
|
||||
}
|
||||
|
||||
if (vm.imgSize.height.indexOf('%') != -1) {
|
||||
img_height = `${(parseInt(vm.imgSize.height) / 100) * parentHeight}px`
|
||||
} else {
|
||||
img_height = vm.imgSize.height
|
||||
}
|
||||
|
||||
if (vm.barSize.width.indexOf('%') != -1) {
|
||||
bar_width = `${(parseInt(vm.barSize.width) / 100) * parentWidth}px`
|
||||
} else {
|
||||
bar_width = vm.barSize.width
|
||||
}
|
||||
|
||||
if (vm.barSize.height.indexOf('%') != -1) {
|
||||
bar_height = `${(parseInt(vm.barSize.height) / 100) * parentHeight}px`
|
||||
} else {
|
||||
bar_height = vm.barSize.height
|
||||
}
|
||||
|
||||
return { imgWidth: img_width, imgHeight: img_height, barWidth: bar_width, barHeight: bar_height }
|
||||
}
|
||||
|
||||
export const _code_chars = [
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
7,
|
||||
8,
|
||||
9,
|
||||
'a',
|
||||
'b',
|
||||
'c',
|
||||
'd',
|
||||
'e',
|
||||
'f',
|
||||
'g',
|
||||
'h',
|
||||
'i',
|
||||
'j',
|
||||
'k',
|
||||
'l',
|
||||
'm',
|
||||
'n',
|
||||
'o',
|
||||
'p',
|
||||
'q',
|
||||
'r',
|
||||
's',
|
||||
't',
|
||||
'u',
|
||||
'v',
|
||||
'w',
|
||||
'x',
|
||||
'y',
|
||||
'z',
|
||||
'A',
|
||||
'B',
|
||||
'C',
|
||||
'D',
|
||||
'E',
|
||||
'F',
|
||||
'G',
|
||||
'H',
|
||||
'I',
|
||||
'J',
|
||||
'K',
|
||||
'L',
|
||||
'M',
|
||||
'N',
|
||||
'O',
|
||||
'P',
|
||||
'Q',
|
||||
'R',
|
||||
'S',
|
||||
'T',
|
||||
'U',
|
||||
'V',
|
||||
'W',
|
||||
'X',
|
||||
'Y',
|
||||
'Z'
|
||||
]
|
||||
export const _code_color1 = ['#fffff0', '#f0ffff', '#f0fff0', '#fff0f0']
|
||||
export const _code_color2 = ['#FF0033', '#006699', '#993366', '#FF9900', '#66CC66', '#FF33CC']
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user