This commit is contained in:
chenxf 2026-04-08 09:24:18 +08:00
parent d9498eaad4
commit 295866e1a7
74 changed files with 609 additions and 3356 deletions

View File

@ -1,14 +0,0 @@
# http://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
insert_final_newline = false
trim_trailing_whitespace = false

7
.env
View File

@ -1,4 +1,3 @@
VITE_PROJECT_NAME = '东莞年报填报服务'
VITE_BASE_API = '/aiceps-gd-server'
# VITE_PUBLICPATH = '/aiceps-dg-app'
VITE_PUBLICPATH = '/aiceps-app'
VITE_PROJECT_NAME = '企业智能年报移动系统'
VITE_BASE_API = '/mobile-api'
VITE_PUBLICPATH = '/mobile'

View File

@ -1,9 +0,0 @@
NODE_ENV = production
# just a flag
ENV = 'staging'
VUE_APP_ENVIRONMENT = 'staging'
# base api
VUE_APP_BASE_API = '/stage-api'

View File

@ -1,4 +0,0 @@
build/*.js
src/assets
public
dist

View File

@ -1,198 +0,0 @@
module.exports = {
root: true,
parserOptions: {
parser: 'babel-eslint',
sourceType: 'module'
},
env: {
browser: true,
node: true,
es6: true,
},
extends: ['plugin:vue/recommended', 'eslint:recommended'],
// add your custom rules here
//it is base on https://github.com/vuejs/eslint-config-vue
rules: {
"vue/max-attributes-per-line": [2, {
"singleline": 10,
"multiline": {
"max": 1,
"allowFirstLine": false
}
}],
"vue/singleline-html-element-content-newline": "off",
"vue/multiline-html-element-content-newline":"off",
"vue/name-property-casing": ["error", "PascalCase"],
"vue/no-v-html": "off",
'accessor-pairs': 2,
'arrow-spacing': [2, {
'before': true,
'after': true
}],
'block-spacing': [2, 'always'],
'brace-style': [2, '1tbs', {
'allowSingleLine': true
}],
'camelcase': [0, {
'properties': 'always'
}],
'comma-dangle': [2, 'never'],
'comma-spacing': [2, {
'before': false,
'after': true
}],
'comma-style': [2, 'last'],
'constructor-super': 2,
'curly': [2, 'multi-line'],
'dot-location': [2, 'property'],
'eol-last': 2,
'eqeqeq': ["error", "always", {"null": "ignore"}],
'generator-star-spacing': [2, {
'before': true,
'after': true
}],
'handle-callback-err': [2, '^(err|error)$'],
'indent': [2, 2, {
'SwitchCase': 1
}],
'jsx-quotes': [2, 'prefer-single'],
'key-spacing': [2, {
'beforeColon': false,
'afterColon': true
}],
'keyword-spacing': [2, {
'before': true,
'after': true
}],
'new-cap': [2, {
'newIsCap': true,
'capIsNew': false
}],
'new-parens': 2,
'no-array-constructor': 2,
'no-caller': 2,
'no-console': 'off',
'no-class-assign': 2,
'no-cond-assign': 2,
'no-const-assign': 2,
'no-control-regex': 0,
'no-delete-var': 2,
'no-dupe-args': 2,
'no-dupe-class-members': 2,
'no-dupe-keys': 2,
'no-duplicate-case': 2,
'no-empty-character-class': 2,
'no-empty-pattern': 2,
'no-eval': 2,
'no-ex-assign': 2,
'no-extend-native': 2,
'no-extra-bind': 2,
'no-extra-boolean-cast': 2,
'no-extra-parens': [2, 'functions'],
'no-fallthrough': 2,
'no-floating-decimal': 2,
'no-func-assign': 2,
'no-implied-eval': 2,
'no-inner-declarations': [2, 'functions'],
'no-invalid-regexp': 2,
'no-irregular-whitespace': 2,
'no-iterator': 2,
'no-label-var': 2,
'no-labels': [2, {
'allowLoop': false,
'allowSwitch': false
}],
'no-lone-blocks': 2,
'no-mixed-spaces-and-tabs': 2,
'no-multi-spaces': 2,
'no-multi-str': 2,
'no-multiple-empty-lines': [2, {
'max': 1
}],
'no-native-reassign': 2,
'no-negated-in-lhs': 2,
'no-new-object': 2,
'no-new-require': 2,
'no-new-symbol': 2,
'no-new-wrappers': 2,
'no-obj-calls': 2,
'no-octal': 2,
'no-octal-escape': 2,
'no-path-concat': 2,
'no-proto': 2,
'no-redeclare': 2,
'no-regex-spaces': 2,
'no-return-assign': [2, 'except-parens'],
'no-self-assign': 2,
'no-self-compare': 2,
'no-sequences': 2,
'no-shadow-restricted-names': 2,
'no-spaced-func': 2,
'no-sparse-arrays': 2,
'no-this-before-super': 2,
'no-throw-literal': 2,
'no-trailing-spaces': 2,
'no-undef': 2,
'no-undef-init': 2,
'no-unexpected-multiline': 2,
'no-unmodified-loop-condition': 2,
'no-unneeded-ternary': [2, {
'defaultAssignment': false
}],
'no-unreachable': 2,
'no-unsafe-finally': 2,
'no-unused-vars': [2, {
'vars': 'all',
'args': 'none'
}],
'no-useless-call': 2,
'no-useless-computed-key': 2,
'no-useless-constructor': 2,
'no-useless-escape': 0,
'no-whitespace-before-property': 2,
'no-with': 2,
'one-var': [2, {
'initialized': 'never'
}],
'operator-linebreak': [2, 'after', {
'overrides': {
'?': 'before',
':': 'before'
}
}],
'padded-blocks': [2, 'never'],
'quotes': [2, 'single', {
'avoidEscape': true,
'allowTemplateLiterals': true
}],
'semi': [2, 'never'],
'semi-spacing': [2, {
'before': false,
'after': true
}],
'space-before-blocks': [2, 'always'],
'space-before-function-paren': [2, 'never'],
'space-in-parens': [2, 'never'],
'space-infix-ops': 2,
'space-unary-ops': [2, {
'words': true,
'nonwords': false
}],
'spaced-comment': [2, 'always', {
'markers': ['global', 'globals', 'eslint', 'eslint-disable', '*package', '!', ',']
}],
'template-curly-spacing': [2, 'never'],
'use-isnan': 2,
'valid-typeof': 2,
'wrap-iife': [2, 'any'],
'yield-star-spacing': [2, 'both'],
'yoda': [2, 'never'],
'prefer-const': 2,
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
'object-curly-spacing': [2, 'always', {
objectsInObjects: false
}],
'array-bracket-spacing': [2, 'never']
}
}

599
.github/copilot-instructions.md vendored Normal file
View File

@ -0,0 +1,599 @@
# Youfool-LLM 前端开发最佳实践
本文档为 Youfool PMS Web 项目的前端开发最佳实践,专门用于指导 LLM 进行规范化的前端编码。
---
## 1. 技术栈与约束
### 1.1 核心框架
- **Vue.js**: 3.3.4 (选项式 API 优先)
- **UI 框架**: Element Plus 2.7.4 (仅桌面端框架)
- **状态管理**: Vuex 4.1.0 (模块化结构)
- **路由**: Vue Router 4.2.5 (Hash 模式路由)
- **构建工具**: Vite 4.4.5 (自定义插件)
- **HTTP 客户端**: Axios 1.6.0 (综合请求封装)
- **图表**: ECharts 5.6.0 (数据可视化)
- **样式**: SCSS + PostCSS px-to-rem 转换
### 1.2 开发约束
- **仅支持桌面端**:系统专为桌面环境设计,不兼容小屏幕设备(如手机、平板)
- **最小分辨率**:设计最小支持宽度为 1200px推荐使用 1920px 或更高分辨率
- **固定布局策略**:采用固定布局而非响应式布局,确保在桌面端的一致性体验
- **无需移动端适配**:开发时无需考虑移动端兼容性、触摸交互等移动特性
---
## 2. 项目架构
### 2.1 目录结构
```
src/
├── api/ # 按业务域组织的 API 服务模块
├── components/ # 可复用 Vue 组件和 EasyComponent 系统
├── extends/ # 可复用 Vue 指令
├── icons/ # 整个项目所有的svg图标
├── layout/ # 布局组件 (Web 等)
├── plugins/ # 自定义 Vue 插件和 EasyComponent 系统
├── router/ # Vue Router 配置,支持基于角色的访问控制
├── store/ # Vuex 模块 (app、user、permission、contract)
├── utils/ # 工具函数和请求封装
├── views/ # 按业务域组织的页面组件
└── styles/ # 全局 SCSS 样式
```
**注意**:模拟数据存放在 `src/mock/` 目录(产品设计阶段)
### 2.2 核心系统
#### 2.2.1 EasyComponent 插件系统
- **配置驱动组件**: EasyForm、EasyTable、EditTable、EasyDialog
- **动态表单生成**: 基础选项加载与验证
- **业务扩展**: `src/components/EasyComponentExtend/`
- **桌面端专用**: 专注于桌面端用户体验,不考虑移动端适配
#### 2.2.2 API 架构
- **模块化结构**: 中文文件名匹配业务域
- **集中请求封装**: `src/utils/request.js` 配置拦截器
- **标准响应格式**: `{code, data, msg}`
- **自动 token 注入**: 401/403 自动登出
#### 2.2.3 路由架构
- **路由配置文件**: `src/router/routes.js` (所有路由配置的实际存放位置)
- **路由结构**:
- `constantRoutes`: 常量路由公开访问如登录、首页、404等
- `asyncRoutes`: 异步路由(需要权限控制,动态加载的业务路由)
- **路由注册**: 使用 `handlerImport` 包装动态导入
- **⚠️ 重要**: 路由配置以实际代码文件 `src/router/routes.js` 为准,新增或修改路由必须在该文件中进行
---
## 3. 编码规范
### 3.1 代码风格
#### 3.1.1 ESLint 规范强制执行
**重要性**:⭐⭐⭐⭐⭐
- 项目配置了严格的 ESLint 规则,不符合规范的代码将被编译拦截
- 提交前必须执行 `npm run lint` 确保代码通过检查
- 所有文件必须以换行符结尾 (eol-last 规则)
#### 3.1.2 命名约定
- **业务域文件**: 使用中文业务域 + 英文技术名
- **组件名**: PascalCase
- **变量名**: camelCase
- **常量名**: UPPER_SNAKE_CASE
- **CSS 类名**: kebab-case
#### 3.1.3 通用规范
- 遵循 Vue.js 官方风格指南
- 遵循 Element Plus 组件使用规范
### 3.2 Vue 3 规范
#### 3.2.1 API 风格
- 严格遵守 Vue 3.3.4 语法规范
- 使用**选项式 API 优先**
- 正确使用 JavaScript ES6+ 特性
#### 3.2.2 响应式数据定义
**所有响应式数据定义在 `data()` 中**
```javascript
export default {
data() {
return {
// 基础类型
count: 0,
message: 'hello',
isVisible: true,
// 对象和数组
formData: {
name: '',
email: '',
age: 0
},
chartOptions: {
title: { text: '图表标题' },
series: []
}
}
}
}
```
#### 3.2.3 组件导入规范
```javascript
// 使用动态导入和 handlerImport
const component = () => handlerImport(import('@/views/路径/组件.vue'))
```
### 3.3 样式编写规范
#### 3.3.1 样式位置
**所有样式必须写在组件的 `<style lang="scss" scoped>` 标签中**
```vue
<!-- ✅ 正确 -->
<style lang="scss" scoped>
.chart-container {
width: 100%;
height: 400px;
}
</style>
<!-- ❌ 错误:外部样式文件无法被预处理器转换 -->
<script>
import './styles.css'
</script>
```
#### 3.3.2 单位使用
- **px 单位**:在样式代码中直接使用 px构建工具会自动转换为 rem
- **rem 单位**:由 PostCSS 自动转换 px → rem手写不应使用 rem
```scss
// 正确:使用 px 单位
.container {
width: 300px;
height: 200px;
margin: 16px;
}
```
#### 3.3.3 Style 标签显式声明
```vue
<!-- ✅ 正确:显式声明 SCSS -->
<style lang="scss" scoped>
/* 组件样式 */
</style>
<!-- ❌ 错误:没有显式声明 SCSS -->
<style scoped>
/* 样式代码 */
</style>
```
### 3.4 调试信息规范
- **禁止**: 除捕获异常外,不要在控制台中打印任何调试信息 chenxf2025年12月23日
- **允许**: 异常捕获时的 console.error
---
## 4. 设计规范
### 4.1 屏幕适配
- **仅支持桌面端**:系统专为桌面环境设计,不兼容小屏幕设备(如手机、平板)
- **最小屏幕宽度**:设计最小支持宽度为 1200px推荐使用 1920px 或更高分辨率
### 4.2 UI 组件使用
- **主要框架**: Element Plus
- **组件尺寸**: 优先使用 `medium``large`
- **布局组件**: 使用 Element Plus Layout
### 4.3 样式设计要求
- **固定单位**:使用 px 作为主要单位,配合 PostCSS px-to-rem 转换
- **最小交互区域**:按钮、链接等可交互元素最小尺寸为 32px × 32px
- **字体大小**:正文字体不小于 14px标题字体根据层级递增
- **色彩对比度**:确保文字与背景的对比度符合 WCAG 2.1 AA 标准
---
## 5. 路由配置
### 5.1 基础配置
#### 5.1.1 路由配置文件
- **实际存放位置**: `src/router/routes.js`
- **⚠️ 重要**: 新增或修改路由必须在该文件中进行
#### 5.1.2 路由结构
- `constantRoutes`: 常量路由公开访问如登录、首页、404等
- `asyncRoutes`: 异步路由(需要权限控制,动态加载的业务路由)
### 5.2 父子路由配置
#### 5.2.1 配置原则
当配置带有子路由的菜单路由时,父路由组件必须包含 `<router-view>` 来渲染子路由内容。
#### 5.2.2 错误示例 ❌
```javascript
// 错误:父路由直接使用页面组件
{
path: '/gzt/datacenter',
redirect: '/gzt/datacenter/overview',
component: () => handlerImport(import('@/views/工作台/数据分析中心/index.vue')),
meta: {
title: '数据分析中心',
icon: 'menu8-2',
keepAlive: false,
isMenu: true
},
children: [
{
path: '/gzt/datacenter/overview',
component: () => handlerImport(import('@/views/工作台/数据分析中心/index.vue')),
meta: {
title: '总览分析',
isSubMenu: true
}
}
]
}
```
**问题**:父路由组件没有 `<router-view>`,子路由无法正确渲染。
#### 5.2.3 正确示例 ✅
```javascript
// 正确:使用 Empty 布局组件作为父路由
{
path: '/gzt/datacenter',
redirect: '/gzt/datacenter/overview',
component: Empty, // 使用带有 <router-view> 的布局组件
meta: {
title: '数据分析中心',
icon: 'menu8-2',
keepAlive: false,
isMenu: true
},
children: [
{
path: '/gzt/datacenter/overview',
component: () => handlerImport(import('@/views/工作台/数据分析中心/index.vue')),
meta: {
title: '总览分析',
isSubMenu: true
}
},
{
path: '/gzt/datacenter/personal-performance',
component: () => handlerImport(import('@/views/数据分析中心/个人绩效分析/index.vue')),
meta: {
title: '个人绩效分析',
isSubMenu: true,
keepAlive: true
}
}
]
}
```
### 5.3 关键原则
1. **父子路由分离**:父路由负责布局,子路由负责内容
2. **布局组件选择**:使用 `Empty` 组件或包含 `<router-view>` 的布局组件
3. **重定向配置**:设置合适的默认子路由重定向
4. **元信息配置**:正确区分 `isMenu``isSubMenu` 属性
### 5.4 常用布局组件
- `Empty`:空布局组件,仅包含 `<router-view>`,适用于需要嵌套子路由的场景
- `WebLayout`:适用于本项目的默认布局
### 5.5 路由组织规范
```javascript
// 所有页面路由应在父路由的 children 中 chenxf2025年12月23日
// 路径需要继承父路由,并写全路径
{
path: '/contract/detail/functionList',
children: [
{
path: '/contract/detail/functionList/detail', // ✅ 正确:继承父路径并写全路径
},
{
path: '/detail' // ❌ 错误:不应使用不是父路由作为前缀的路径
}
]
}
```
**规范来源**:合同功能清单路由组织实践 chenxf2025年12月23日
### 5.6 注意事项
- 父路由的 `component` 不能直接使用业务页面组件
- 子路由的 `path` 应使用父路由的路径作为前缀
- 确保布局组件已正确导入并注册
---
## 6. 组件开发实践
### 6.1 组件拆分原则
#### 6.1.1 业务模块组件拆分
- **文件夹组织**: 相关代码放在一个文件夹内
- **避免重复**: 禁止同名 .vue 文件和同名文件夹并存
- **共享组件**: 放在小范围公共文件中
#### 6.1.2 列表页面组件选型
**使用 `<edit-table>` 场景**
- 条件查询筛选功能
- 简单弹窗编辑/查看功能
- 行内编辑功能
**使用 `<easy-table>` 场景**
- 纯展示列表页面
#### 6.1.3 CSS 类名命名
- 参照其他相似页面保持一致
- 以方便维护公共 CSS 类为原则
- 遵循项目现有的命名约定
### 6.2 EasyForm 开发规范
#### 6.2.1 侧边查询条件
- **使用组件**: 应使用 `<easy-form>` 开发 chenxf2025年12月23日
- **字段复用**: 尽可能复用列表页面组件中定义的 fields chenxf2025年12月23日
- **职责分离**:
- 侧边查询条件组件只负责生成查询条件数据 chenxf2025年12月23日
- 通过事件通知父组件执行搜索查询 chenxf2025年12月23日
#### 6.2.2 字段配置
**必填校验**
```javascript
// 使用 required: true chenxf2025年12月23日
{
prop: 'fieldName',
required: true,
// ❌ 错误:不需要在 rules 中定义必填校验
// rules: [{ required: true, message: '请输入', trigger: 'blur' }]
}
```
**占位符**
```javascript
// 在 formProps.placeholders 中定义 chenxf2025年12月23日
fields: [
{
formProps: {
placeholders: '请输入内容' // 仅在需要自定义时填写一般由EasyForm组件自动生成
}
}
]
// ❌ 错误:不在 field 中定义 placeholder
```
**默认值**
```javascript
// ❌ 错误非业务要求场景下fields 中不应定义 defaultValue chenxf2025年12月23日
// ✅ 正确:直接对 formData 赋值
this.formData.fieldName = '初始值'
```
#### 6.2.3 码值配置
**本地码值表**
```javascript
// 使用 options 字段
{
prop: 'status',
label: '状态',
type: 'select',
options: [
{ label: '启用', value: '1' },
{ label: '禁用', value: '0' }
]
}
```
**全局码值表**
```javascript
// main.js 中定义
BaseOptionsLoader: (baseCode)=>{
if(baseCode==='statusOptions'){
return [
{ label: '启用', value: '1' },
{ label: '禁用', value: '0' }
]
}
}
// field 中引用
{
prop: 'status',
type: 'select',
optionsBaseCode: 'statusOptions'
}
// ❌ 错误:不要在 data 中声明码表 chenxf2025年12月23日
// ❌ 错误:不要使用 formatter 进行码值转换 chenxf2025年12月23日
```
#### 6.2.4 组件属性定义
```javascript
// element-plus 组件属性应在 formProps 中定义 chenxf2025年12月23日
formConfig: {
formProps: {
// ✅ 正确:在这里定义
size: 'large',
labelWidth: '120px'
}
}
// ❌ 错误:不在 fieldProps 中定义 element-plus 属性
```
#### 6.2.5 字段单位
```javascript
// 使用 append 字段定义单位 chenxf2025年12月23日
{
prop: 'price',
label: '价格',
append: '元'
}
```
#### 6.2.6 码表值类型
- **优先使用**: string 类型 chenxf2025年12月23日
- **例外**: 当接口明确定义为 number 类型时
### 6.3 EasyTable 开发规范
#### 6.3.1 格式化字段使用规范
**✅ 应该使用 formatter 的场景**
- 日期格式化(如时间戳转为 YYYY-MM-DD
- 数字格式化(如金额添加千分位)
- 文本处理(如截断、拼接等)
**编写位置**tableProps.formatter chenxf2025年12月23日
```javascript
tableConfig: {
tableProps: {
// ✅ 正确:在这里定义
formatter: (row, column, cellValue) => {
// 示例:日期格式化
return dayjs(cellValue).format('YYYY-MM-DD HH:mm:ss')
}
}
}
```
#### 6.3.2 码值转换规范
**❌ 不应该使用 formatter 的场景**
- 状态码转换(如 0/1 → 禁用/启用)
- 类型码转换(如 type=1,2,3 → 业务类型文本)
**正确做法**:使用 options 字段定义对应的码值表 chenxf2025年12月23日
```javascript
// ✅ 正确:使用 options 字段定义码值表
{
prop: 'status',
label: '状态',
options: [
{ label: '启用', value: '1' },
{ label: '禁用', value: '0' }
]
}
// ❌ 错误:不要使用 formatter 进行码值转换 chenxf2025年12月23日
```
### 6.4 通用开发规范
#### 6.4.1 异步操作处理
```javascript
// 按钮 handler 中的异步操作应 return Promise chenxf2025年12月23日
handlers: {
async handleSubmit() {
// ✅ 正确return Promise
return await this.saveData()
}
}
```
#### 6.4.2 编辑查看页面复用
- **原则**: 如查看页面不存在和编辑页面复杂的结构差异 chenxf2025年12月23日
- **实现**:
- 编辑和查看页面应使用同一个页面 chenxf2025年12月23日
- 使用 `<easy-form>` 开发 chenxf2025年12月23日
- 通过 `formConfig.isView` 字段控制是否处于编辑或查看状态 chenxf2025年12月23日
#### 6.4.3 字段复用
- **原则**: 同一个业务文件下easy-component 的各个组件的 fields 应尽可能复用 chenxf2025年12月23日
- **实践**: 提取公共 fields 配置,多处引用
#### 6.4.4 错误处理规范
**API 调用必须使用 try-catch 包裹** zhenghl2025年12月24日
```javascript
// ✅ 正确示例
async getUnreadCount() {
try {
const response = await getUnreadMessageCount()
this.unreadCount = response || 0
} catch (error) {
console.error('获取未读消息数量失败:', error)
}
}
// ❌ 错误示例:缺少错误处理
async getUnreadCount() {
const response = await getUnreadMessageCount()
this.unreadCount = response || 0
}
```
**规范要求**
- 所有 API 调用必须使用 try-catch 包裹
- 错误信息使用 console.error 记录
- 异常处理逻辑应包含用户友好的错误提示
---
## 7. 附录
### 7.1 规范来源说明
本规范文档的内容综合了项目开发实践和代码审查总结。其中 `docs/fix/` 目录记录了代码审查中发现的问题和规范要求,是当前最佳实践的重要来源。这些规范经过实践验证,是项目开发中必须遵守的重要规则。
---
*文档版本: v1.2.0*
*最后更新时间: 2025-12-24*
*维护者: Youfool 前端团队*

View File

@ -1,5 +0,0 @@
language: node_js
node_js: 10
script: npm run test
notifications:
email: false

View File

@ -1,7 +0,0 @@
module.exports = {
presets: [
['@vue/app', {
useBuiltIns: 'entry'
}]
]
}

View File

@ -1,101 +0,0 @@
const path = require('path')
const fs = require('fs')
const axios = require('axios')
const crypto = require('crypto')
const readline = require('readline')
/**
* 生成字典插件 v1.0
* youfool
*/
class constantFile {
constructor(options) {
this.options = options
}
apply(compiler) {
compiler.hooks.environment.tap('constantFile', async (compilation, callback) => {
// 只在开发环境
if (process.env.ENV === 'development') {
const projectPath = path.join(__dirname, '../../')
const constantPath = projectPath + '/src/constant'
fs.mkdir(constantPath, function (error) {
if (error) {
return false
}
// 获取字典参数
axios.get(this.options.api).then((res) => {
const { code, data } = res.data
if (code === 0) {
for (const module of data) {
// 模块
const moduleName = Object.keys(module)[0]
const filePath = constantPath + '/' + moduleName + 'Constant.js'
let fileStr = templateStr(module[moduleName])
const hash = crypto.createHash('md5')
hash.update(fileStr)
const md5 = hash.digest('hex')
// 判断之前的文件是否存在
if (fs.existsSync(filePath)) {
const oldFile = readline.createInterface({
input: fs.createReadStream(filePath)
})
let oldMd5
oldFile.on('line', function (line) { // 事件监听
if (!oldMd5) {
// 解析旧文件的字符md5
oldMd5 = line.replace('// ', '')
if (oldMd5 === md5) {
oldFile.close()
} else {
// 不相同则重新生成常量文件
fileStr = `// ${md5}\n` + fileStr
fs.writeFileSync(filePath, fileStr, 'utf8')
}
}
})
} else {
// 不相同则重新生成常量文件
fileStr = `// ${md5}\n` + fileStr
fs.writeFileSync(filePath, fileStr, 'utf8')
}
}
}
}).catch((e) => { })
})
}
})
}
}
/**
* 生成文件字符
*/
function templateStr(dictTypes) {
const moduleName = dictTypes[0].module
const moduleDescription = dictTypes[0].moduleDescription
// 开头
const head = `/**
* ${moduleName}${moduleDescription || ''}
* 本文件不能手动修改需要通过代码生成器生成
*/\n`
// 底部
let bottom = 'export default {'
// 遍历类型
let content = ''
for (const dictType of dictTypes) {
content += `/**
*${dictType.name}
*${dictType.typeDescription || ''}
*/`
for (const dictCode of dictType.dictCodes) {
const attribute = `${dictType.type.toUpperCase()}_${dictCode.constant.toUpperCase()}`
content += `\nconst ${attribute} = '${dictCode.code}'// ${dictCode.label}${dictCode.description || ''}`
bottom += ` ${attribute},`
}
content += `\n`
}
// 去除最后的逗号
bottom = bottom.substr(0, bottom.length - 1) + ` }`
return head + '\n' + content + '\n' + bottom + '\n'
}
module.exports = constantFile

View File

@ -1,117 +0,0 @@
const path = require('path')
const fs = require('fs')
const compressing = require('compressing')
const axios = require('axios')
const child_process = require('child_process')
const packageJson = require('../package.json')
function parseTime(time, format = 'yyyy-MM-dd hh:mm:ss') {
const date = time instanceof Date ? time : new Date(time)
const o = {
'M+': date.getMonth() + 1, // 月份
'd+': date.getDate(), // 日
'h+': date.getHours(), // 小时
'm+': date.getMinutes(), // 分
's+': date.getSeconds(), // 秒
'q+': Math.floor((date.getMonth() + 3) / 3), // 季度
'S': date.getMilliseconds() // 毫秒
}
if (/(y+)/.test(format)) {
format = format.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length))
}
for (const k in o) {
if (new RegExp('(' + k + ')').test(format)) {
format = format.replace(RegExp.$1, (RegExp.$1.length === 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length)))
}
}
return format
}
/**
* 打包插件 v2.0
* youfool
*/
class IncrePack {
apply(compiler) {
if (process.env.VUE_APP_WEBPACK_CMD !== 'build') {
return
}
const date = new Date()
const projectPath = path.join(__dirname, '../')
const distPath = projectPath + 'dist'
const versionPath = `${projectPath}src/version.js`
let hash = '000000'
try {
hash = child_process.execSync('git rev-parse HEAD').slice(0, 6)
} catch (e) {
console.log('------------------读取版本Hash失败---------------')
console.warn(e)
}
const codeVersion = `${parseTime(date, 'yyyy-MM-dd hh:mm:ss')} ${hash} ${process.env.VUE_APP_ENVIRONMENT}`
compiler.hooks.beforeRun.tapAsync('SetVersion', async(compilation, callback) => {
const data = `/** 本文件由打包插件自动生成和修改 */\nexport default '${codeVersion}'\n`
fs.writeFileSync(versionPath, data)
callback()
})
compiler.hooks.done.tap('SetVersion', async(compilation) => {
const data = `/** 本文件由打包插件自动生成和修改 */\nexport default ''\n`
fs.writeFileSync(versionPath, data)
})
compiler.hooks.done.tap('IncrePack', async(compilation) => {
let versionJson = {
artifactId: packageJson.name,
version: packageJson.version,
appId: packageJson.appId,
codeId: packageJson.codeId,
codeVersion
}
if (packageJson.increApi) {
// 获取版本信息
try {
console.log('------------------正在写入升级记录---------------')
const res = await axios.default({
url: packageJson.increApi + '?appId=' + packageJson.appId + '&codeId=' + packageJson.codeId,
method: 'get',
timeout: 5000
})
const { code, data } = res.data
if (code === 0 && data) {
versionJson = {
...versionJson,
artifactId: packageJson.name,
upgradeId: data.upgradeId,
version: data.version,
releaseTime: data.releaseTime,
fromCommit: data.fromCommit,
untilCommit: data.untilCommit,
newFeatures: data.newFeatures,
repair: data.repair,
other: data.other,
operId: data.operId,
operName: data.operName,
}
console.log('------------------写入升级记录成功---------------')
}
} catch (e) {
console.log(e.message)
console.log('------------------提交升级记录到远端失败---------------')
}
}
fs.mkdirSync(distPath + '/increpack-config')
fs.writeFileSync(distPath + '/increpack-config/version.json', JSON.stringify(versionJson), 'utf8')
const increName = `${packageJson.name}-${process.env.VUE_APP_ENVIRONMENT}-${parseTime(date, 'yyyy-MM-dd')}-${hash}.zip`
// 打包压缩
const tempFile = projectPath + '/' + increName
compressing.zip.compressDir(distPath, tempFile, { ignoreBase: true })
.then(() => {
// 剪切回dist目录下
fs.renameSync(tempFile, distPath + '/' + increName)
console.log('------------------打包成功------------------')
})
.catch(err => {
console.error(err)
})
})
}
}
module.exports = IncrePack

View File

@ -1,35 +0,0 @@
const { run } = require('runjs')
const chalk = require('chalk')
const config = require('../vue.config.js')
const rawArgv = process.argv.slice(2)
const args = rawArgv.join(' ')
if (process.env.npm_config_preview || rawArgv.includes('--preview')) {
const report = rawArgv.includes('--report')
run(`vue-cli-service build ${args}`)
const port = 9526
const publicPath = config.publicPath
var connect = require('connect')
var serveStatic = require('serve-static')
const app = connect()
app.use(
publicPath,
serveStatic('./dist', {
index: ['index.html', '/']
})
)
app.listen(port, function () {
console.log(chalk.green(`> Preview at http://localhost:${port}${publicPath}`))
if (report) {
console.log(chalk.green(`> Report at http://localhost:${port}${publicPath}report.html`))
}
})
} else {
run(`vue-cli-service build ${args}`)
}

View File

@ -1,8 +0,0 @@
// https://github.com/michael-ciniawsky/postcss-load-config
module.exports = {
'plugins': {
// to edit target browsers: use "browserslist" field in package.json
'autoprefixer': {}
}
}

View File

@ -1,22 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<meta http-equiv="Expires" content="0">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Cache-control" content="no-cache">
<meta http-equiv="Cache" content="no-cache">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= webpackConfig.name %></title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= webpackConfig.name %> doesn't work properly without JavaScript enabled. Please enable it
to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

View File

@ -1,21 +0,0 @@
// import request from '@/utils/request'
export function getList(params) {
// return request({
// url: '/table/list',
// method: 'get',
// params
// })
return Promise.resolve({
items: [
{
id: 0,
title: '111',
status: 'published',
author: 'name',
display_time: '2020-02-02',
pageviews: '111'
}
]
})
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

View File

@ -1,25 +0,0 @@
// 公共全局样式页面需配合scss使用
// 一级标题文字大小
$font-size-classA-title: 30px;
// 下边距
$margin-bottom-20: 20px;
// 主题颜色
$color-theme: #ccc;
// 一级字体颜色
$color-classA-font-weight: blue;
// 等等

View File

@ -1,539 +0,0 @@
/* Logo 字体 */
@font-face {
font-family: "iconfont logo";
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834');
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg');
}
.logo {
font-family: "iconfont logo";
font-size: 160px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* tabs */
.nav-tabs {
position: relative;
}
.nav-tabs .nav-more {
position: absolute;
right: 0;
bottom: 0;
height: 42px;
line-height: 42px;
color: #666;
}
#tabs {
border-bottom: 1px solid #eee;
}
#tabs li {
cursor: pointer;
width: 100px;
height: 40px;
line-height: 40px;
text-align: center;
font-size: 16px;
border-bottom: 2px solid transparent;
position: relative;
z-index: 1;
margin-bottom: -1px;
color: #666;
}
#tabs .active {
border-bottom-color: #f00;
color: #222;
}
.tab-container .content {
display: none;
}
/* 页面布局 */
.main {
padding: 30px 100px;
width: 960px;
margin: 0 auto;
}
.main .logo {
color: #333;
text-align: left;
margin-bottom: 30px;
line-height: 1;
height: 110px;
margin-top: -50px;
overflow: hidden;
*zoom: 1;
}
.main .logo a {
font-size: 160px;
color: #333;
}
.helps {
margin-top: 40px;
}
.helps pre {
padding: 20px;
margin: 10px 0;
border: solid 1px #e7e1cd;
background-color: #fffdef;
overflow: auto;
}
.icon_lists {
width: 100% !important;
overflow: hidden;
*zoom: 1;
}
.icon_lists li {
width: 100px;
margin-bottom: 10px;
margin-right: 20px;
text-align: center;
list-style: none !important;
cursor: default;
}
.icon_lists li .code-name {
line-height: 1.2;
}
.icon_lists .icon {
display: block;
height: 100px;
line-height: 100px;
font-size: 42px;
margin: 10px auto;
color: #333;
-webkit-transition: font-size 0.25s linear, width 0.25s linear;
-moz-transition: font-size 0.25s linear, width 0.25s linear;
transition: font-size 0.25s linear, width 0.25s linear;
}
.icon_lists .icon:hover {
font-size: 100px;
}
.icon_lists .svg-icon {
/* 通过设置 font-size 来改变图标大小 */
width: 1em;
/* 图标和文字相邻时,垂直对齐 */
vertical-align: -0.15em;
/* 通过设置 color 来改变 SVG 的颜色/fill */
fill: currentColor;
/* path stroke 溢出 viewBox 部分在 IE 下会显示
normalize.css 中也包含这行 */
overflow: hidden;
}
.icon_lists li .name,
.icon_lists li .code-name {
color: #666;
}
/* markdown 样式 */
.markdown {
color: #666;
font-size: 14px;
line-height: 1.8;
}
.highlight {
line-height: 1.5;
}
.markdown img {
vertical-align: middle;
max-width: 100%;
}
.markdown h1 {
color: #404040;
font-weight: 500;
line-height: 40px;
margin-bottom: 24px;
}
.markdown h2,
.markdown h3,
.markdown h4,
.markdown h5,
.markdown h6 {
color: #404040;
margin: 1.6em 0 0.6em 0;
font-weight: 500;
clear: both;
}
.markdown h1 {
font-size: 28px;
}
.markdown h2 {
font-size: 22px;
}
.markdown h3 {
font-size: 16px;
}
.markdown h4 {
font-size: 14px;
}
.markdown h5 {
font-size: 12px;
}
.markdown h6 {
font-size: 12px;
}
.markdown hr {
height: 1px;
border: 0;
background: #e9e9e9;
margin: 16px 0;
clear: both;
}
.markdown p {
margin: 1em 0;
}
.markdown>p,
.markdown>blockquote,
.markdown>.highlight,
.markdown>ol,
.markdown>ul {
width: 80%;
}
.markdown ul>li {
list-style: circle;
}
.markdown>ul li,
.markdown blockquote ul>li {
margin-left: 20px;
padding-left: 4px;
}
.markdown>ul li p,
.markdown>ol li p {
margin: 0.6em 0;
}
.markdown ol>li {
list-style: decimal;
}
.markdown>ol li,
.markdown blockquote ol>li {
margin-left: 20px;
padding-left: 4px;
}
.markdown code {
margin: 0 3px;
padding: 0 5px;
background: #eee;
border-radius: 3px;
}
.markdown strong,
.markdown b {
font-weight: 600;
}
.markdown>table {
border-collapse: collapse;
border-spacing: 0px;
empty-cells: show;
border: 1px solid #e9e9e9;
width: 95%;
margin-bottom: 24px;
}
.markdown>table th {
white-space: nowrap;
color: #333;
font-weight: 600;
}
.markdown>table th,
.markdown>table td {
border: 1px solid #e9e9e9;
padding: 8px 16px;
text-align: left;
}
.markdown>table th {
background: #F7F7F7;
}
.markdown blockquote {
font-size: 90%;
color: #999;
border-left: 4px solid #e9e9e9;
padding-left: 0.8em;
margin: 1em 0;
}
.markdown blockquote p {
margin: 0;
}
.markdown .anchor {
opacity: 0;
transition: opacity 0.3s ease;
margin-left: 8px;
}
.markdown .waiting {
color: #ccc;
}
.markdown h1:hover .anchor,
.markdown h2:hover .anchor,
.markdown h3:hover .anchor,
.markdown h4:hover .anchor,
.markdown h5:hover .anchor,
.markdown h6:hover .anchor {
opacity: 1;
display: inline-block;
}
.markdown>br,
.markdown>p>br {
clear: both;
}
.hljs {
display: block;
background: white;
padding: 0.5em;
color: #333333;
overflow-x: auto;
}
.hljs-comment,
.hljs-meta {
color: #969896;
}
.hljs-string,
.hljs-variable,
.hljs-template-variable,
.hljs-strong,
.hljs-emphasis,
.hljs-quote {
color: #df5000;
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-type {
color: #a71d5d;
}
.hljs-literal,
.hljs-symbol,
.hljs-bullet,
.hljs-attribute {
color: #0086b3;
}
.hljs-section,
.hljs-name {
color: #63a35c;
}
.hljs-tag {
color: #333333;
}
.hljs-title,
.hljs-attr,
.hljs-selector-id,
.hljs-selector-class,
.hljs-selector-attr,
.hljs-selector-pseudo {
color: #795da3;
}
.hljs-addition {
color: #55a532;
background-color: #eaffea;
}
.hljs-deletion {
color: #bd2c00;
background-color: #ffecec;
}
.hljs-link {
text-decoration: underline;
}
/* 代码高亮 */
/* PrismJS 1.15.0
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */
/**
* prism.js default theme for JavaScript, CSS and HTML
* Based on dabblet (http://dabblet.com)
* @author Lea Verou
*/
code[class*="language-"],
pre[class*="language-"] {
color: black;
background: none;
text-shadow: 0 1px white;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[class*="language-"]::-moz-selection,
pre[class*="language-"] ::-moz-selection,
code[class*="language-"]::-moz-selection,
code[class*="language-"] ::-moz-selection {
text-shadow: none;
background: #b3d4fc;
}
pre[class*="language-"]::selection,
pre[class*="language-"] ::selection,
code[class*="language-"]::selection,
code[class*="language-"] ::selection {
text-shadow: none;
background: #b3d4fc;
}
@media print {
code[class*="language-"],
pre[class*="language-"] {
text-shadow: none;
}
}
/* Code blocks */
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
}
:not(pre)>code[class*="language-"],
pre[class*="language-"] {
background: #f5f2f0;
}
/* Inline code */
:not(pre)>code[class*="language-"] {
padding: .1em;
border-radius: .3em;
white-space: normal;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: slategray;
}
.token.punctuation {
color: #999;
}
.namespace {
opacity: .7;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: #905;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #690;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #9a6e3a;
background: hsla(0, 0%, 100%, .5);
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #07a;
}
.token.function,
.token.class-name {
color: #DD4A68;
}
.token.regex,
.token.important,
.token.variable {
color: #e90;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}

View File

@ -1,331 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>IconFont Demo</title>
<link rel="shortcut icon" href="https://gtms04.alicdn.com/tps/i4/TB1_oz6GVXXXXaFXpXXJDFnIXXX-64-64.ico" type="image/x-icon"/>
<link rel="stylesheet" href="https://g.alicdn.com/thx/cube/1.3.2/cube.min.css">
<link rel="stylesheet" href="demo.css">
<link rel="stylesheet" href="iconfont.css">
<script src="iconfont.js"></script>
<!-- jQuery -->
<script src="https://a1.alicdn.com/oss/uploads/2018/12/26/7bfddb60-08e8-11e9-9b04-53e73bb6408b.js"></script>
<!-- 代码高亮 -->
<script src="https://a1.alicdn.com/oss/uploads/2018/12/26/a3f714d0-08e6-11e9-8a15-ebf944d7534c.js"></script>
</head>
<body>
<div class="main">
<h1 class="logo"><a href="https://www.iconfont.cn/" title="iconfont 首页" target="_blank">&#xe86b;</a></h1>
<div class="nav-tabs">
<ul id="tabs" class="dib-box">
<li class="dib active"><span>Unicode</span></li>
<li class="dib"><span>Font class</span></li>
<li class="dib"><span>Symbol</span></li>
</ul>
<a href="https://www.iconfont.cn/manage/index?manage_type=myprojects&projectId=1496577" target="_blank" class="nav-more">查看项目</a>
</div>
<div class="tab-container">
<div class="content unicode" style="display: block;">
<ul class="icon_lists dib-box">
<li class="dib">
<span class="icon iconfont">&#xeb95;</span>
<div class="name">icon_group</div>
<div class="code-name">&amp;#xeb95;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xeb98;</span>
<div class="name">icon_mobilephone</div>
<div class="code-name">&amp;#xeb98;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xeb94;</span>
<div class="name">icon_dmail</div>
<div class="code-name">&amp;#xeb94;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xeb97;</span>
<div class="name">icon_message</div>
<div class="code-name">&amp;#xeb97;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xeb99;</span>
<div class="name">icon_left</div>
<div class="code-name">&amp;#xeb99;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xeb9a;</span>
<div class="name">icon_next_arrow</div>
<div class="code-name">&amp;#xeb9a;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xeb9f;</span>
<div class="name">icon_statistics</div>
<div class="code-name">&amp;#xeb9f;</div>
</li>
</ul>
<div class="article markdown">
<h2 id="unicode-">Unicode 引用</h2>
<hr>
<p>Unicode 是字体在网页端最原始的应用方式,特点是:</p>
<ul>
<li>兼容性最好,支持 IE6+,及所有现代浏览器。</li>
<li>支持按字体的方式去动态调整图标大小,颜色等等。</li>
<li>但是因为是字体,所以不支持多色。只能使用平台里单色的图标,就算项目里有多色图标也会自动去色。</li>
</ul>
<blockquote>
<p>注意:新版 iconfont 支持多色图标,这些多色图标在 Unicode 模式下将不能使用如果有需求建议使用symbol 的引用方式</p>
</blockquote>
<p>Unicode 使用步骤如下:</p>
<h3 id="-font-face">第一步:拷贝项目下面生成的 <code>@font-face</code></h3>
<pre><code class="language-css"
>@font-face {
font-family: 'iconfont';
src: url('iconfont.eot');
src: url('iconfont.eot?#iefix') format('embedded-opentype'),
url('iconfont.woff2') format('woff2'),
url('iconfont.woff') format('woff'),
url('iconfont.ttf') format('truetype'),
url('iconfont.svg#iconfont') format('svg');
}
</code></pre>
<h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
<pre><code class="language-css"
>.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
</code></pre>
<h3 id="-">第三步:挑选相应图标并获取字体编码,应用于页面</h3>
<pre>
<code class="language-html"
>&lt;span class="iconfont"&gt;&amp;#x33;&lt;/span&gt;
</code></pre>
<blockquote>
<p>"iconfont" 是你项目下的 font-family。可以通过编辑项目查看默认是 "iconfont"。</p>
</blockquote>
</div>
</div>
<div class="content font-class">
<ul class="icon_lists dib-box">
<li class="dib">
<span class="icon iconfont chinawealicon_group"></span>
<div class="name">
icon_group
</div>
<div class="code-name">.chinawealicon_group
</div>
</li>
<li class="dib">
<span class="icon iconfont chinawealicon_mobilephone"></span>
<div class="name">
icon_mobilephone
</div>
<div class="code-name">.chinawealicon_mobilephone
</div>
</li>
<li class="dib">
<span class="icon iconfont chinawealicon_dmail"></span>
<div class="name">
icon_dmail
</div>
<div class="code-name">.chinawealicon_dmail
</div>
</li>
<li class="dib">
<span class="icon iconfont chinawealicon_message"></span>
<div class="name">
icon_message
</div>
<div class="code-name">.chinawealicon_message
</div>
</li>
<li class="dib">
<span class="icon iconfont chinawealicon_left"></span>
<div class="name">
icon_left
</div>
<div class="code-name">.chinawealicon_left
</div>
</li>
<li class="dib">
<span class="icon iconfont chinawealicon_next_arrow"></span>
<div class="name">
icon_next_arrow
</div>
<div class="code-name">.chinawealicon_next_arrow
</div>
</li>
<li class="dib">
<span class="icon iconfont chinawealicon_statistics"></span>
<div class="name">
icon_statistics
</div>
<div class="code-name">.chinawealicon_statistics
</div>
</li>
</ul>
<div class="article markdown">
<h2 id="font-class-">font-class 引用</h2>
<hr>
<p>font-class 是 Unicode 使用方式的一种变种,主要是解决 Unicode 书写不直观,语意不明确的问题。</p>
<p>与 Unicode 使用方式相比,具有如下特点:</p>
<ul>
<li>兼容性良好,支持 IE8+,及所有现代浏览器。</li>
<li>相比于 Unicode 语意明确,书写更直观。可以很容易分辨这个 icon 是什么。</li>
<li>因为使用 class 来定义图标,所以当要替换图标时,只需要修改 class 里面的 Unicode 引用。</li>
<li>不过因为本质上还是使用的字体,所以多色图标还是不支持的。</li>
</ul>
<p>使用步骤如下:</p>
<h3 id="-fontclass-">第一步:引入项目下面生成的 fontclass 代码:</h3>
<pre><code class="language-html">&lt;link rel="stylesheet" href="./iconfont.css"&gt;
</code></pre>
<h3 id="-">第二步:挑选相应图标并获取类名,应用于页面:</h3>
<pre><code class="language-html">&lt;span class="iconfont chinawealxxx"&gt;&lt;/span&gt;
</code></pre>
<blockquote>
<p>"
iconfont" 是你项目下的 font-family。可以通过编辑项目查看默认是 "iconfont"。</p>
</blockquote>
</div>
</div>
<div class="content symbol">
<ul class="icon_lists dib-box">
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#chinawealicon_group"></use>
</svg>
<div class="name">icon_group</div>
<div class="code-name">#chinawealicon_group</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#chinawealicon_mobilephone"></use>
</svg>
<div class="name">icon_mobilephone</div>
<div class="code-name">#chinawealicon_mobilephone</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#chinawealicon_dmail"></use>
</svg>
<div class="name">icon_dmail</div>
<div class="code-name">#chinawealicon_dmail</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#chinawealicon_message"></use>
</svg>
<div class="name">icon_message</div>
<div class="code-name">#chinawealicon_message</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#chinawealicon_left"></use>
</svg>
<div class="name">icon_left</div>
<div class="code-name">#chinawealicon_left</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#chinawealicon_next_arrow"></use>
</svg>
<div class="name">icon_next_arrow</div>
<div class="code-name">#chinawealicon_next_arrow</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#chinawealicon_statistics"></use>
</svg>
<div class="name">icon_statistics</div>
<div class="code-name">#chinawealicon_statistics</div>
</li>
</ul>
<div class="article markdown">
<h2 id="symbol-">Symbol 引用</h2>
<hr>
<p>这是一种全新的使用方式,应该说这才是未来的主流,也是平台目前推荐的用法。相关介绍可以参考这篇<a href="">文章</a>
这种用法其实是做了一个 SVG 的集合,与另外两种相比具有如下特点:</p>
<ul>
<li>支持多色图标了,不再受单色限制。</li>
<li>通过一些技巧,支持像字体那样,通过 <code>font-size</code>, <code>color</code> 来调整样式。</li>
<li>兼容性较差,支持 IE9+,及现代浏览器。</li>
<li>浏览器渲染 SVG 的性能一般,还不如 png。</li>
</ul>
<p>使用步骤如下:</p>
<h3 id="-symbol-">第一步:引入项目下面生成的 symbol 代码:</h3>
<pre><code class="language-html">&lt;script src="./iconfont.js"&gt;&lt;/script&gt;
</code></pre>
<h3 id="-css-">第二步:加入通用 CSS 代码(引入一次就行):</h3>
<pre><code class="language-html">&lt;style&gt;
.icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
&lt;/style&gt;
</code></pre>
<h3 id="-">第三步:挑选相应图标并获取类名,应用于页面:</h3>
<pre><code class="language-html">&lt;svg class="icon" aria-hidden="true"&gt;
&lt;use xlink:href="#icon-xxx"&gt;&lt;/use&gt;
&lt;/svg&gt;
</code></pre>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function () {
$('.tab-container .content:first').show()
$('#tabs li').click(function (e) {
var tabContent = $('.tab-container .content')
var index = $(this).index()
if ($(this).hasClass('active')) {
return
} else {
$('#tabs li').removeClass('active')
$(this).addClass('active')
tabContent.hide().eq(index).fadeIn()
}
})
})
</script>
</body>
</html>

View File

@ -1,54 +0,0 @@
@font-face {font-family: "iconfont";
src: url('iconfont.eot?t=1573086485730'); /* IE9 */
src: url('iconfont.eot?t=1573086485730#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAYEAAsAAAAAC8QAAAW2AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCDVAqJZIdjATYCJAMgCxIABCAFhG0HgRMb6AkR1aQbkP08sJst8g+IFvVghy0TO6S6+gz+28x5+xZYFm+wiCvE9czJichSh7QeszMXSMW+zqg6DUAQwN/325Sh2i1kKsyUCIPvssx/sMPLhVElq9sAAav+/+eY6SKxnue3rZ0ii7qoaTgcJdDAMi7KW+8NbAeKpxKdzU16wXsaCAAefogBKSqpagIHFpyGoGzurNYp4GxWsCEkAs4g9jnKgnwAETjGxtwB8L7698SFJMIBDEQU3LPqLMXTYXa1u4ao4BaMpwKE/NwArqcACiAGAAuQhb7e2aB6IgYU/DuXRR4Ajp/FAK4OV69ryO1m1HZXl7wtCQ481Dl6CNhK/edBDAlAxOC0cmCnJyWAq120gPanDGaQj64LbGABVzcbGMDVI4YPrl6wQQy4hqyQAM2tVgPQAuQ1gHxB2Bwt5UkikCo2LSZYqlZrBZWUu0qjUWdUKjnRGl7WG9YZluZ8RKzRXYZ2g6GrjxBr1imvzq4umY44HMCTJz4bHeUnY3v2hLRrebtfZ/j8vb7Ck6aUIyEnAjSbsralpTmdZCg+KbFv6KLT/qQZ3QORug59R4tzZFQOqmZegl/Oq7ed87IaRmpHRoIHnS1T2nZbd9l3CDtXb9lhZHt2hiq27/YW9e4Km6o4+tBX3P8gRX7skZ9k6PGarq07u7XTd9ijLJ29u7frZnS0GSz2HWCFnTJN224isu7iV2viI1mkGiG6cat9l3V3205hh0xLTR+1Xab46ZVZLJdtPespa2o/pu8khE9tT1fldo/WGR2CNqLdrrd0Wg2tXW26SDtzSvs2fYO614/Ua2iUxNm2ghF28HKHo3lkZJTTOV7IaVEcf+xPHaEnT8ZSUd1UqrlGHvBTWfiA+G2v+etFVr7mj4zg2LI1pGT1/gFtmbn74lqt300exMwXjy4oo0UZ+Qn5K7z2jZbuiGsz3kIS2muNYV81cKYqc73uizsbzjj8HWfW7/muTue4UpOkcewAM2bv7y99JpTW1nbV1KBkouylpH80GVjxJSYsWDGbzCILl0+awI6qaBo7cTCoOsIc6VE9trdrEec/nMxzBm31X1URw0Hzx1Y20VFwm5QaH36VPHhywi46THclDKsr9psuCM0cuGaBtiFl08od1mCjLcV4o+xGCmUbg607ko3dWHFwglKjyFFolBlYlSyYM4RmSY6kWaBcmLZpd0fsQu/de7RZm9858Z5CP1mpUULUf3NST67sim8ebf6n6X6/ev3keui/YduxYoMg6LF52izdnt1799q8bJJYV1tc94PA9QjdOptXD6+2Sd/WSW2cbWVg7fzFP68emD6U7awh1Zanzu30AH35Upq53fn0yverOvZO4MJn1vdqXHh65xhZRduvXTvSN3Rc9fvvh+MJfuC/VJ8l/81LfLCBA8D9gGVoAuAepmY6GQ5Az/wH7uv0AU0H3Icot6UGjvs75hfqAbgvUF5vOiKW4eWK9U1S5fzGyf4kA5++eFOnmt3D+fomw9msZbFl239dANz/x9wUnI3r1Zkojc3kvAFRjAHwvAPY+jPAK77KU687lQIER2cCQ8IXKE4IksXGgIhMCohxTMCLVnpaxsNiPpIUQJQ3CAi1/cBQOg+U2l0ki/0SRPS+AzF1FHgt87ijTFiz+MLFSBQ5Tf3SrIx7Izh0rZU/UIxtIlaFSvtAbBWmxLgEZzpED8ljx5KpuC9VQxbhjkroeWhbpoXCNTI9z1Qdgvh4i987nadx56wVEpBQkCNTfZFZMqxn5P5q7br9AxRGrYSEtHyLfoCwqulJojgJMZChto/Vsi61S0wKd0tZzCCWaynrkBLmhpZPMLLQf1ENMupsZorYIBDPulnias/l67spPQHA4x7BjSGUsERExERCOCLFSBVGhfA4HA2+jtOqxVDq4M+Wd0nVbgthbVJg9Um0MHrQl/RYNEpEeP5FrSZaSfEqs44DAA==') format('woff2'),
url('iconfont.woff?t=1573086485730') format('woff'),
url('iconfont.ttf?t=1573086485730') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
url('iconfont.svg?t=1573086485730#iconfont') format('svg'); /* iOS 4.1- */
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
[class^="el-icon-chinaweal"], [class*=" el-icon-chinaweal"] {
font-family:"iconfont" !important;
/* 以下内容参照第三方图标库本身的规则 */
font-size: inherit;
font-style:normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.chinawealicon_group:before {
content: "\eb95";
}
.chinawealicon_mobilephone:before {
content: "\eb98";
}
.chinawealicon_dmail:before {
content: "\eb94";
}
.chinawealicon_message:before {
content: "\eb97";
}
.chinawealicon_left:before {
content: "\eb99";
}
.chinawealicon_next_arrow:before {
content: "\eb9a";
}
.chinawealicon_statistics:before {
content: "\eb9f";
}

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -1,58 +0,0 @@
{
"id": "1496577",
"name": "众望通前端框架",
"font_family": "iconfont",
"css_prefix_text": "chinaweal",
"description": "",
"glyphs": [
{
"icon_id": "7766747",
"name": "icon_group",
"font_class": "icon_group",
"unicode": "eb95",
"unicode_decimal": 60309
},
{
"icon_id": "7766758",
"name": "icon_mobilephone",
"font_class": "icon_mobilephone",
"unicode": "eb98",
"unicode_decimal": 60312
},
{
"icon_id": "7766759",
"name": "icon_dmail",
"font_class": "icon_dmail",
"unicode": "eb94",
"unicode_decimal": 60308
},
{
"icon_id": "7766760",
"name": "icon_message",
"font_class": "icon_message",
"unicode": "eb97",
"unicode_decimal": 60311
},
{
"icon_id": "7766764",
"name": "icon_left",
"font_class": "icon_left",
"unicode": "eb99",
"unicode_decimal": 60313
},
{
"icon_id": "7766765",
"name": "icon_next_arrow",
"font_class": "icon_next_arrow",
"unicode": "eb9a",
"unicode_decimal": 60314
},
{
"icon_id": "7766801",
"name": "icon_statistics",
"font_class": "icon_statistics",
"unicode": "eb9f",
"unicode_decimal": 60319
}
]
}

View File

@ -1,47 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<!--
2013-9-30: Created.
-->
<svg>
<metadata>
Created by iconfont
</metadata>
<defs>
<font id="iconfont" horiz-adv-x="1024" >
<font-face
font-family="iconfont"
font-weight="500"
font-stretch="normal"
units-per-em="1024"
ascent="896"
descent="-128"
/>
<missing-glyph />
<glyph glyph-name="icon_group" unicode="&#60309;" d="M927.602509 143.783986l-0.23229 0.227174h29.299303c-6.963599 16.205077-17.3389 28.650527-32.123628 38.505989-11.113105 7.407714-25.723871 13.758352-46.514383 20.424169-5.110391 1.638313-10.54824 3.289929-17.350157 5.284353-3.324722 0.975211-15.70161 4.557806-18.429745 5.355985-88.184435 25.798573-130.320091 54.177923-130.320091 130.420375 0 23.708981 6.788613 44.428885 18.857487 65.177441 3.789303 6.513344 7.748475 12.511965 13.272281 20.383236-2.675946-3.813862 9.016351 12.731976 11.486613 16.3729 15.338337 22.601764 21.530362 39.328727 21.530362 66.057485V583.99087c0 42.020022-14.459317 72.682369-42.056862 89.419566-29.714765 11.600199-47.465035 27.124777-53.251831 46.573735-1.813299 6.094812-2.127454 19.222807 6.708796 25.606191 4.488221 3.242857 10.018168 4.727675 16.588816 4.455475l0.721431-0.555655-0.228197 0.403182c87.37807-12.452613 135.514393-79.288834 135.514393-165.902494v-71.996754c0-95.995331-65.146743-119.993908-65.146742-167.992085 0-71.996754 112.100124-60.234873 184.111204-108.23305 25.090445-16.72287 43.566238-38.886659 55.428404-66.491367 13.953803-32.473599-1.058099-70.109778-33.531698-84.064604a63.968917 63.968917 0 0 0-9.199522-3.148714l-0.032746-0.109493-0.391926 0.001023-0.179079-0.045026-0.022513 0.046049c-31.827893 0.151449-51.17759 12.536524-58.051137 37.155225-3.069919 10.667967 1.203408 18.968004 12.821003 24.90011l0.722454-0.228198zM375.726314 367.090888c14.781658-24.329105 22.99062-48.275493 22.99062-75.65712 0-87.273692-49.405223-119.287827-159.104671-150.295028-3.53143-0.997724-19.150152-5.370311-23.319102-6.550183-8.773827-2.484587-15.809057-4.539386-22.470781-6.585999-30.438243-9.346879-51.907207-18.339694-68.656682-29.290093-29.495778-19.284205-48.27754-45.904493-57.852616-82.694397h798.615786c-9.473769 36.729529-28.263717 63.308885-57.944713 82.604346-16.529465 10.745738-37.448914 19.615757-66.565045 28.721135-6.931876 2.167363-14.261818 4.338818-23.385617 6.948249-4.428869 1.266853-20.75265 5.875824-24.308638 6.890944-108.392686 30.92943-157.548222 63.22088-157.548223 150.252049 0 27.154453 8.003278 50.982138 22.450315 75.206866 4.670369 7.831362 9.629311 15.159258 16.617469 24.87555-3.558036-4.947685 11.968589 16.485463 15.33322 21.321608 22.096251 31.757285 31.472805 56.463989 31.472806 94.585216v92.567255c0 94.390787-55.488779 151.992693-154.733107 151.992693-100.638071 0-155.976424-57.491389-154.74948-151.154605l0.005117-0.838088v-42.306548c0-28.01403 0-28.01403-0.005117-51.098795-0.497327-37.983079 8.776897-62.33879 31.306007-94.169753 3.366677-4.756327 18.307971-25.061792 15.144931-20.73116 7.015787-9.603729 12.005428-16.8559 16.707521-24.594142zM248.578472 599.990263c-1.616824 123.423007 76.646658 215.989239 218.740909 215.989239 140.467195 0 218.729653-92.313475 218.729654-215.989239v-92.567256c0-123.423007-85.874833-154.277736-85.874833-215.989239 0-92.566232 147.767462-77.444836 242.692414-139.15634 43.26027-28.123524 71.603805-68.215638 85.031629-120.276341 8.827039-34.224476-11.760858-69.124334-45.985334-77.951373a63.993476 63.993476 0 0 0-15.983019-2.028193l-798.61681 0.001024c-35.343973 0-63.996546 28.652574-63.996547 63.996546 0 5.437849 0.692778 10.854209 2.062986 16.117073 13.531178 51.995211 41.785685 92.042299 84.765569 120.141264 94.390787 61.711504 244.575298 46.590108 244.575298 139.15634 0 61.711504-87.757716 92.567255-86.141916 215.989239v92.567256z" horiz-adv-x="1024" />
<glyph glyph-name="icon_mobilephone" unicode="&#60312;" d="M512-63.977871c17.672498 0 31.998785 14.326287 31.998785 31.998785s-14.326287 31.998785-31.998785 31.998785-31.998785-14.326287-31.998785-31.998785 14.326287-31.998785 31.998785-31.998785zM304.009945 799.980109c-26.508747 0-47.998177-21.48943-47.998177-47.998177v-671.967318c0-26.508747 21.48943-47.997154 47.998177-47.997154h415.98011c26.508747 0 47.997154 21.48943 47.997154 47.997154V751.982956c0 26.508747-21.48943 47.998177-47.997154 47.998177H304.009945z m-15.999392 63.996547h447.978894c53.016471 0 95.995331-42.97886 95.995331-95.995331v-767.96265c0-53.016471-42.97886-95.995331-95.995331-95.995331H288.010553c-53.016471 0-95.995331 42.97886-95.995331 95.995331V767.981325c0 53.017494 42.97886 95.995331 95.995331 95.995331z" horiz-adv-x="1024" />
<glyph glyph-name="icon_dmail" unicode="&#60308;" d="M842.458317 631.666706c13.075807 11.887748 33.313733 10.923794 45.201482-2.153036 11.887748-13.075807 10.923794-33.313733-2.153037-45.201482L576.573691 303.463756c-36.614919-33.286104-92.532463-33.286104-129.147382 0L138.492214 584.312188c-13.07683 11.887748-14.039761 32.125675-2.152013 45.201482 11.887748 13.07683 32.124651 14.040784 45.201482 2.153036l308.934094-280.849456c12.204973-11.095709 30.843472-11.095709 43.048446 0L842.458317 631.666706zM99.555413 701.265854c-17.522072 0-31.726585-14.204513-31.726585-31.726586v-571.077513c0-17.522072 14.204513-31.726585 31.726585-31.726585h824.889174c17.522072 0 31.726585 14.204513 31.726585 31.726585V669.539268c0 17.522072-14.204513 31.726585-31.726585 31.726586H99.555413z m0 63.452147h824.889174c52.566216 0 95.179756-42.61354 95.179756-95.179756v-571.077513c0-52.566216-42.61354-95.179756-95.179756-95.179757H99.555413c-52.566216 0-95.179756 42.61354-95.179756 95.179757V669.539268c0 52.565193 42.61354 95.178733 95.179756 95.178733z" horiz-adv-x="1024" />
<glyph glyph-name="icon_message" unicode="&#60311;" d="M320.009338 422.927591c-26.508747 0-47.998177 21.48943-47.998178 47.998177s21.48943 47.998177 47.998178 47.998178 47.998177-21.48943 47.998177-47.998178-21.490453-47.998177-47.998177-47.998177z m191.990662 0c-26.508747 0-47.998177 21.48943-47.998177 47.998177s21.48943 47.998177 47.998177 47.998178 47.998177-21.48943 47.998177-47.998178-21.48943-47.998177-47.998177-47.998177z m191.990662 0c-26.508747 0-47.997154 21.48943-47.997154 47.998177s21.48943 47.998177 47.997154 47.998178c26.508747 0 47.998177-21.48943 47.998178-47.998178s-21.48943-47.998177-47.998178-47.998177zM304.009945 25.803945l184.698583 143.654794a63.99757 63.99757 0 0 0 39.289841 13.481036h351.983563c17.672498 0 31.998785 14.326287 31.998785 31.998785V726.912977c0 17.672498-14.326287 31.998785-31.998785 31.998785H144.017044c-17.672498 0-31.998785-14.326287-31.998784-31.998785v-511.975441c0-17.672498 14.326287-31.998785 31.998784-31.998784h95.995332c35.344996 0 63.996546-28.652574 63.996546-63.996547v-93.13826z m223.989447 93.13826L317.478701-44.795996c-20.924565-16.274662-51.080376-12.504802-67.355037 8.419763a47.994084 47.994084 0 0 0-10.110265 29.468149V118.942205h-95.995331c-53.016471 0-95.995331 42.97886-95.995331 95.995331V726.912977c0 53.016471 42.97886 95.995331 95.995331 95.995331h735.964888c53.016471 0 95.995331-42.97886 95.995331-95.995331v-511.975441c0-53.016471-42.97886-95.995331-95.995331-95.995331H527.999392z" horiz-adv-x="1024" />
<glyph glyph-name="icon_left" unicode="&#60313;" d="M376.24206 384l384.647497-384.647497c12.496615-12.496615 12.496615-32.756031 0-45.252647l-22.626323-22.626323c-12.496615-12.496615-32.756031-12.496615-45.252647 0L263.110443 361.373677c-12.496615 12.496615-12.496615 32.756031 0 45.252646L693.010587 836.526467c12.496615 12.495592 32.756031 12.495592 45.252647 0l22.626323-22.626323c12.496615-12.495592 12.496615-32.756031 0-45.252647L376.24206 384z" horiz-adv-x="1024" />
<glyph glyph-name="icon_next_arrow" unicode="&#60314;" d="M384.561539-9.148102c-12.365632-12.647041-32.082696-12.551874-44.161802 0.342808l-50.324152 53.724599c-12.023848 12.836353-11.748578 33.491789 0.654916 46.177715l266.968307 273.051863c12.385075 12.667507 12.005428 32.915667-0.891299 45.26595L279.229562 675.252387c-12.877285 12.332886-13.356193 32.516578-1.109264 45.040822l55.647392 56.909128c12.264325 12.542664 32.388664 12.401448 44.645826-0.008187l367.036397-371.605459c12.392238-12.546757 12.409634-32.975019 0.048095-45.616944L384.561539-9.148102z" horiz-adv-x="1024" />
<glyph glyph-name="icon_statistics" unicode="&#60319;" d="M575.996546 766.76973v-414.767492c0-17.672498-14.32731-31.998785-31.998784-31.998784H129.229247c16.33913-214.787878 195.795315-383.981325 414.769538-383.981325 229.739405 0 415.980109 186.240705 415.980109 415.980109-0.001023 218.972177-169.195493 398.428362-383.982348 414.767492z m-31.997761-766.751055c-159.148673 0-296.509111 107.977223-338.671373 255.987209h338.671373c52.931536 0 95.995331 43.062771 95.995331 95.995331V690.673611c148.012032-42.163285 255.987209-179.52577 255.987209-338.671373 0-194.084347-157.898193-351.983563-351.98254-351.983563zM512 415.998785V830.928982C272.41025 815.15881 80.84119 623.588727 65.072041 384h414.929174c17.671475 0 31.998785 14.326287 31.998785 31.998785z m-63.99757 31.998785H139.173736c36.119639 152.354943 156.472727 272.710079 308.828694 308.829717v-308.829717z" horiz-adv-x="1024" />
</font>
</defs></svg>

Before

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

0
src/assets/images/maintain.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

@ -1,78 +0,0 @@
<template>
<el-breadcrumb class="app-breadcrumb" separator="/">
<transition-group name="breadcrumb">
<el-breadcrumb-item v-for="(item,index) in levelList" :key="item.path">
<span v-if="item.redirect==='noRedirect'||index==levelList.length-1" class="no-redirect">{{ item.meta.title }}</span>
<a v-else @click.prevent="handleLink(item)">{{ item.meta.title }}</a>
</el-breadcrumb-item>
</transition-group>
</el-breadcrumb>
</template>
<script>
import pathToRegexp from 'path-to-regexp'
export default {
data() {
return {
levelList: null
}
},
watch: {
$route() {
this.getBreadcrumb()
}
},
created() {
this.getBreadcrumb()
},
methods: {
getBreadcrumb() {
// only show routes with meta.title
let matched = this.$route.matched.filter(item => item.meta && item.meta.title)
const first = matched[0]
if (!this.isDashboard(first)) {
matched = [{ path: '/dashboard', meta: { title: '首页' }}].concat(matched)
}
this.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false)
},
isDashboard(route) {
const name = route && route.name
if (!name) {
return false
}
return name.trim().toLocaleLowerCase() === 'Dashboard'.toLocaleLowerCase()
},
pathCompile(path) {
// To solve this problem https://github.com/PanJiaChen/vue-element-admin/issues/561
const { params } = this.$route
var toPath = pathToRegexp.compile(path)
return toPath(params)
},
handleLink(item) {
const { redirect, path } = item
if (redirect) {
this.$router.push(redirect)
return
}
this.$router.push(this.pathCompile(path))
}
}
}
</script>
<style lang="scss" scoped>
.app-breadcrumb.el-breadcrumb {
display: inline-block;
font-size: 14px;
line-height: 50px;
margin-left: 8px;
.no-redirect {
color: #97a8be;
cursor: text;
}
}
</style>

View File

@ -1,44 +0,0 @@
<template>
<div style="padding: 0 15px;" @click="toggleClick">
<svg
:class="{'is-active':isActive}"
class="hamburger"
viewBox="0 0 1024 1024"
xmlns="http://www.w3.org/2000/svg"
width="64"
height="64"
>
<path d="M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM142.4 642.1L298.7 519a8.84 8.84 0 0 0 0-13.9L142.4 381.9c-5.8-4.6-14.4-.5-14.4 6.9v246.3a8.9 8.9 0 0 0 14.4 7z" />
</svg>
</div>
</template>
<script>
export default {
name: 'Hamburger',
props: {
isActive: {
type: Boolean,
default: false
}
},
methods: {
toggleClick() {
this.$emit('toggleClick')
}
}
}
</script>
<style scoped>
.hamburger {
display: inline-block;
vertical-align: middle;
width: 20px;
height: 20px;
}
.hamburger.is-active {
transform: rotate(180deg);
}
</style>

View File

@ -1,62 +0,0 @@
<template>
<div v-if="isExternal" :style="styleExternalIcon" class="svg-external-icon svg-icon" v-on="$listeners" />
<svg v-else :class="svgClass" aria-hidden="true" v-on="$listeners">
<use :xlink:href="iconName" />
</svg>
</template>
<script>
// doc: https://panjiachen.github.io/vue-element-admin-site/feature/component/svg-icon.html#usage
import { isExternal } from '@/utils/validate'
export default {
name: 'SvgIcon',
props: {
iconClass: {
type: String,
required: true
},
className: {
type: String,
default: ''
}
},
computed: {
isExternal() {
return isExternal(this.iconClass)
},
iconName() {
return `#icon-${this.iconClass}`
},
svgClass() {
if (this.className) {
return 'svg-icon ' + this.className
} else {
return 'svg-icon'
}
},
styleExternalIcon() {
return {
mask: `url(${this.iconClass}) no-repeat 50% 50%`,
'-webkit-mask': `url(${this.iconClass}) no-repeat 50% 50%`
}
}
}
}
</script>
<style scoped>
.svg-icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
.svg-external-icon {
background-color: currentColor;
mask-size: cover!important;
display: inline-block;
}
</style>

View File

@ -1,9 +0,0 @@
import Vue from 'vue'
import SvgIcon from '@/components/SvgIcon'// svg component
// register globally
Vue.component('svg-icon', SvgIcon)
const req = require.context('./svg', false, /\.svg$/)
const requireAll = requireContext => requireContext.keys().map(requireContext)
requireAll(req)

View File

@ -1 +0,0 @@
<svg width="128" height="100" xmlns="http://www.w3.org/2000/svg"><path d="M27.429 63.638c0-2.508-.893-4.65-2.679-6.424-1.786-1.775-3.94-2.662-6.464-2.662-2.524 0-4.679.887-6.465 2.662-1.785 1.774-2.678 3.916-2.678 6.424 0 2.508.893 4.65 2.678 6.424 1.786 1.775 3.94 2.662 6.465 2.662 2.524 0 4.678-.887 6.464-2.662 1.786-1.775 2.679-3.916 2.679-6.424zm13.714-31.801c0-2.508-.893-4.65-2.679-6.424-1.785-1.775-3.94-2.662-6.464-2.662-2.524 0-4.679.887-6.464 2.662-1.786 1.774-2.679 3.916-2.679 6.424 0 2.508.893 4.65 2.679 6.424 1.785 1.774 3.94 2.662 6.464 2.662 2.524 0 4.679-.888 6.464-2.662 1.786-1.775 2.679-3.916 2.679-6.424zM71.714 65.98l7.215-27.116c.285-1.23.107-2.378-.536-3.443-.643-1.064-1.56-1.762-2.75-2.094-1.19-.33-2.333-.177-3.429.462-1.095.639-1.81 1.573-2.143 2.804l-7.214 27.116c-2.857.237-5.405 1.266-7.643 3.088-2.238 1.822-3.738 4.152-4.5 6.992-.952 3.644-.476 7.098 1.429 10.364 1.905 3.265 4.69 5.37 8.357 6.317 3.667.947 7.143.474 10.429-1.42 3.285-1.892 5.404-4.66 6.357-8.305.762-2.84.619-5.607-.429-8.305-1.047-2.697-2.762-4.85-5.143-6.46zm47.143-2.342c0-2.508-.893-4.65-2.678-6.424-1.786-1.775-3.94-2.662-6.465-2.662-2.524 0-4.678.887-6.464 2.662-1.786 1.774-2.679 3.916-2.679 6.424 0 2.508.893 4.65 2.679 6.424 1.786 1.775 3.94 2.662 6.464 2.662 2.524 0 4.679-.887 6.465-2.662 1.785-1.775 2.678-3.916 2.678-6.424zm-45.714-45.43c0-2.509-.893-4.65-2.679-6.425C68.68 10.01 66.524 9.122 64 9.122c-2.524 0-4.679.887-6.464 2.661-1.786 1.775-2.679 3.916-2.679 6.425 0 2.508.893 4.65 2.679 6.424 1.785 1.774 3.94 2.662 6.464 2.662 2.524 0 4.679-.888 6.464-2.662 1.786-1.775 2.679-3.916 2.679-6.424zm32 13.629c0-2.508-.893-4.65-2.679-6.424-1.785-1.775-3.94-2.662-6.464-2.662-2.524 0-4.679.887-6.464 2.662-1.786 1.774-2.679 3.916-2.679 6.424 0 2.508.893 4.65 2.679 6.424 1.785 1.774 3.94 2.662 6.464 2.662 2.524 0 4.679-.888 6.464-2.662 1.786-1.775 2.679-3.916 2.679-6.424zM128 63.638c0 12.351-3.357 23.78-10.071 34.286-.905 1.372-2.19 2.058-3.858 2.058H13.93c-1.667 0-2.953-.686-3.858-2.058C3.357 87.465 0 76.037 0 63.638c0-8.613 1.69-16.847 5.071-24.703C8.452 31.08 13 24.312 18.714 18.634c5.715-5.68 12.524-10.199 20.429-13.559C47.048 1.715 55.333.035 64 .035c8.667 0 16.952 1.68 24.857 5.04 7.905 3.36 14.714 7.88 20.429 13.559 5.714 5.678 10.262 12.446 13.643 20.301 3.38 7.856 5.071 16.09 5.071 24.703z"/></svg>

Before

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -1 +0,0 @@
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M96.258 57.462h31.421C124.794 27.323 100.426 2.956 70.287.07v31.422a32.856 32.856 0 0 1 25.971 25.97zm-38.796-25.97V.07C27.323 2.956 2.956 27.323.07 57.462h31.422a32.856 32.856 0 0 1 25.97-25.97zm12.825 64.766v31.421c30.46-2.885 54.507-27.253 57.713-57.712H96.579c-2.886 13.466-13.146 23.726-26.292 26.291zM31.492 70.287H.07c2.886 30.46 27.253 54.507 57.713 57.713V96.579c-13.466-2.886-23.726-13.146-26.291-26.292z"/></svg>

Before

Width:  |  Height:  |  Size: 497 B

View File

@ -1 +0,0 @@
<svg class="icon" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="128" height="128"><defs><style/></defs><path d="M512 128q69.675 0 135.51 21.163t115.498 54.997 93.483 74.837 73.685 82.006 51.67 74.837 32.17 54.827L1024 512q-2.347 4.992-6.315 13.483T998.87 560.17t-31.658 51.669-44.331 59.99-56.832 64.34-69.504 60.16-82.347 51.5-94.848 34.687T512 896q-69.675 0-135.51-21.163t-115.498-54.826-93.483-74.326-73.685-81.493-51.67-74.496-32.17-54.997L0 513.707q2.347-4.992 6.315-13.483t18.816-34.816 31.658-51.84 44.331-60.33 56.832-64.683 69.504-60.331 82.347-51.84 94.848-34.816T512 128.085zm0 85.333q-46.677 0-91.648 12.331t-81.152 31.83-70.656 47.146-59.648 54.485-48.853 57.686-37.675 52.821-26.325 43.99q12.33 21.674 26.325 43.52t37.675 52.351 48.853 57.003 59.648 53.845T339.2 767.02t81.152 31.488T512 810.667t91.648-12.331 81.152-31.659 70.656-46.848 59.648-54.186 48.853-57.344 37.675-52.651T927.957 512q-12.33-21.675-26.325-43.648t-37.675-52.65-48.853-57.345-59.648-54.186-70.656-46.848-81.152-31.659T512 213.334zm0 128q70.656 0 120.661 50.006T682.667 512 632.66 632.661 512 682.667 391.339 632.66 341.333 512t50.006-120.661T512 341.333zm0 85.334q-35.328 0-60.33 25.002T426.666 512t25.002 60.33T512 597.334t60.33-25.002T597.334 512t-25.002-60.33T512 426.666z"/></svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -1 +0,0 @@
<svg width="128" height="64" xmlns="http://www.w3.org/2000/svg"><path d="M127.072 7.994c1.37-2.208.914-5.152-.914-6.87-2.056-1.717-4.797-1.226-6.396.982-.229.245-25.586 32.382-55.74 32.382-29.24 0-55.74-32.382-55.968-32.627-1.6-1.963-4.57-2.208-6.397-.49C-.17 3.086-.399 6.275 1.2 8.238c.457.736 5.94 7.36 14.62 14.72L4.17 35.96c-1.828 1.963-1.6 5.152.228 6.87.457.98 1.6 1.471 2.742 1.471s2.284-.49 3.198-1.472l12.564-13.983c5.94 4.416 13.021 8.587 20.788 11.53l-4.797 17.418c-.685 2.699.686 5.397 3.198 6.133h1.37c2.057 0 3.884-1.472 4.341-3.68L52.6 42.83c3.655.736 7.538 1.227 11.422 1.227 3.883 0 7.767-.49 11.422-1.227l4.797 17.173c.457 2.208 2.513 3.68 4.34 3.68.457 0 .914 0 1.143-.246 2.513-.736 3.883-3.434 3.198-6.133l-4.797-17.172c7.767-2.944 14.848-7.114 20.788-11.53l12.336 13.738c.913.981 2.056 1.472 3.198 1.472s2.284-.49 3.198-1.472c1.828-1.963 1.828-4.906.228-6.87l-11.65-13.001c9.366-7.36 14.849-14.474 14.849-14.474z"/></svg>

Before

Width:  |  Height:  |  Size: 944 B

View File

@ -1 +0,0 @@
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M84.068 23.784c-1.02 0-1.877-.32-2.572-.96a8.588 8.588 0 0 1-1.738-2.237 11.524 11.524 0 0 1-1.042-2.621c-.232-.895-.348-1.641-.348-2.238V0h.278c.834 0 1.622.085 2.363.256.742.17 1.645.575 2.711 1.214 1.066.64 2.363 1.535 3.892 2.686 1.53 1.15 3.453 2.664 5.77 4.54 2.502 2.045 4.494 3.771 5.977 5.178 1.483 1.406 2.618 2.6 3.406 3.58.787.98 1.274 1.812 1.46 2.494.185.682.277 1.278.277 1.79v2.046H84.068zM127.3 84.01c.278.682.464 1.535.556 2.558.093 1.023-.37 2.003-1.39 2.94-.463.427-.88.832-1.25 1.215-.372.384-.696.704-.974.96a6.69 6.69 0 0 1-.973.767l-11.816-10.741a44.331 44.331 0 0 0 1.877-1.535 31.028 31.028 0 0 1 1.737-1.406c1.112-.938 2.317-1.343 3.615-1.215 1.297.128 2.363.405 3.197.83.927.427 1.923 1.173 2.989 2.239 1.065 1.065 1.876 2.195 2.432 3.388zM78.23 95.902c2.038 0 3.752-.511 5.143-1.534l-26.969 25.83H18.037c-1.761 0-3.684-.47-5.77-1.407a24.549 24.549 0 0 1-5.838-3.709 21.373 21.373 0 0 1-4.518-5.306c-1.204-2.003-1.807-4.07-1.807-6.202V16.495c0-1.79.44-3.665 1.32-5.626A18.41 18.41 0 0 1 5.04 5.562a21.798 21.798 0 0 1 5.213-3.964C12.198.533 14.237 0 16.37 0h53.24v15.984c0 1.62.278 3.367.834 5.242a16.704 16.704 0 0 0 2.572 5.179c1.159 1.577 2.665 2.898 4.518 3.964 1.853 1.066 4.078 1.598 6.673 1.598h20.295v42.325L85.458 92.45c1.02-1.364 1.529-2.856 1.529-4.476 0-2.216-.857-4.113-2.572-5.69-1.714-1.577-3.776-2.366-6.186-2.366H26.1c-2.409 0-4.448.789-6.116 2.366-1.668 1.577-2.502 3.474-2.502 5.69 0 2.217.834 4.092 2.502 5.626 1.668 1.535 3.707 2.302 6.117 2.302h52.13zM26.1 47.951c-2.41 0-4.449.789-6.117 2.366-1.668 1.577-2.502 3.473-2.502 5.69 0 2.216.834 4.092 2.502 5.626 1.668 1.534 3.707 2.302 6.117 2.302h52.13c2.409 0 4.47-.768 6.185-2.302 1.715-1.534 2.572-3.41 2.572-5.626 0-2.217-.857-4.113-2.572-5.69-1.714-1.577-3.776-2.366-6.186-2.366H26.1zm52.407 64.063l1.807-1.663 3.476-3.196a479.75 479.75 0 0 0 4.587-4.284 500.757 500.757 0 0 1 5.004-4.667c3.985-3.666 8.48-7.758 13.485-12.276l11.677 10.741-13.485 12.404-5.004 4.603-4.587 4.22a179.46 179.46 0 0 0-3.267 3.068c-.88.853-1.367 1.322-1.46 1.407-.463.341-.973.703-1.529 1.087-.556.383-1.112.703-1.668.959-.556.256-1.413.575-2.572.959a83.5 83.5 0 0 1-3.545 1.087 72.2 72.2 0 0 1-3.475.895c-1.112.256-1.946.426-2.502.511-1.112.17-1.854.043-2.224-.383-.371-.426-.464-1.151-.278-2.174.092-.511.278-1.279.556-2.302.278-1.023.602-2.067.973-3.132l1.042-3.005c.325-.938.58-1.577.765-1.918a10.157 10.157 0 0 1 2.224-2.941z"/></svg>

Before

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -1 +0,0 @@
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M115.625 127.937H.063V12.375h57.781v12.374H12.438v90.813h90.813V70.156h12.374z"/><path d="M116.426 2.821l8.753 8.753-56.734 56.734-8.753-8.745z"/><path d="M127.893 37.982h-12.375V12.375H88.706V0h39.187z"/></svg>

Before

Width:  |  Height:  |  Size: 285 B

View File

@ -1 +0,0 @@
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M.002 9.2c0 5.044 3.58 9.133 7.998 9.133 4.417 0 7.997-4.089 7.997-9.133 0-5.043-3.58-9.132-7.997-9.132S.002 4.157.002 9.2zM31.997.066h95.981V18.33H31.997V.066zm0 45.669c0 5.044 3.58 9.132 7.998 9.132 4.417 0 7.997-4.088 7.997-9.132 0-3.263-1.524-6.278-3.998-7.91-2.475-1.63-5.524-1.63-7.998 0-2.475 1.632-4 4.647-4 7.91zM63.992 36.6h63.986v18.265H63.992V36.6zm-31.995 82.2c0 5.043 3.58 9.132 7.998 9.132 4.417 0 7.997-4.089 7.997-9.132 0-5.044-3.58-9.133-7.997-9.133s-7.998 4.089-7.998 9.133zm31.995-9.131h63.986v18.265H63.992V109.67zm0-27.404c0 5.044 3.58 9.133 7.998 9.133 4.417 0 7.997-4.089 7.997-9.133 0-3.263-1.524-6.277-3.998-7.909-2.475-1.631-5.524-1.631-7.998 0-2.475 1.632-4 4.646-4 7.91zm31.995-9.13h31.991V91.4H95.987V73.135z"/></svg>

Before

Width:  |  Height:  |  Size: 821 B

View File

@ -1 +0,0 @@
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M108.8 44.322H89.6v-5.36c0-9.04-3.308-24.163-25.6-24.163-23.145 0-25.6 16.881-25.6 24.162v5.361H19.2v-5.36C19.2 15.281 36.798 0 64 0c27.202 0 44.8 15.281 44.8 38.961v5.361zm-32 39.356c0-5.44-5.763-9.832-12.8-9.832-7.037 0-12.8 4.392-12.8 9.832 0 3.682 2.567 6.808 6.407 8.477v11.205c0 2.718 2.875 4.962 6.4 4.962 3.524 0 6.4-2.244 6.4-4.962V92.155c3.833-1.669 6.393-4.795 6.393-8.477zM128 64v49.201c0 8.158-8.645 14.799-19.2 14.799H19.2C8.651 128 0 121.359 0 113.201V64c0-8.153 8.645-14.799 19.2-14.799h89.6c10.555 0 19.2 6.646 19.2 14.799z"/></svg>

Before

Width:  |  Height:  |  Size: 623 B

View File

@ -1 +0,0 @@
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M.006.064h127.988v31.104H.006V.064zm0 38.016h38.396v41.472H.006V38.08zm0 48.384h38.396v41.472H.006V86.464zM44.802 38.08h38.396v41.472H44.802V38.08zm0 48.384h38.396v41.472H44.802V86.464zM89.598 38.08h38.396v41.472H89.598zm0 48.384h38.396v41.472H89.598z"/><path d="M.006.064h127.988v31.104H.006V.064zm0 38.016h38.396v41.472H.006V38.08zm0 48.384h38.396v41.472H.006V86.464zM44.802 38.08h38.396v41.472H44.802V38.08zm0 48.384h38.396v41.472H44.802V86.464zM89.598 38.08h38.396v41.472H89.598zm0 48.384h38.396v41.472H89.598z"/></svg>

Before

Width:  |  Height:  |  Size: 597 B

View File

@ -1 +0,0 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1568823806344" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3821" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M85.344 0v1024h853.344V0H85.344z m768 938.656H170.688V85.312h682.656v853.344z" p-id="3822"></path><path d="M256 170.656h512v170.656H256V170.656zM426.656 426.656H768V512H426.656v-85.344zM426.656 597.344H768v85.344H426.656v-85.344zM426.656 768H768v85.344H426.656V768zM256 426.656h85.344v426.656H256V426.656z" p-id="3823"></path></svg>

Before

Width:  |  Height:  |  Size: 709 B

View File

@ -1 +0,0 @@
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M126.713 90.023c.858.985 1.287 2.134 1.287 3.447v29.553c0 1.423-.429 2.6-1.287 3.53-.858.93-1.907 1.395-3.146 1.395H97.824c-1.145 0-2.146-.465-3.004-1.395-.858-.93-1.287-2.107-1.287-3.53V93.47c0-.875.19-1.696.572-2.462.382-.766.906-1.368 1.573-1.806a3.84 3.84 0 0 1 2.146-.657h9.725V69.007a3.84 3.84 0 0 0-.43-1.806 3.569 3.569 0 0 0-1.143-1.313 2.714 2.714 0 0 0-1.573-.492h-36.47v23.149h9.725c1.144 0 2.145.492 3.004 1.478.858.985 1.287 2.134 1.287 3.447v29.553c0 .876-.191 1.696-.573 2.463-.38.766-.905 1.368-1.573 1.806a3.84 3.84 0 0 1-2.145.656H51.915a3.84 3.84 0 0 1-2.145-.656c-.668-.438-1.216-1.04-1.645-1.806a4.96 4.96 0 0 1-.644-2.463V93.47c0-1.313.43-2.462 1.288-3.447.858-.986 1.907-1.478 3.146-1.478h9.582v-23.15h-37.9c-.953 0-1.74.356-2.359 1.068-.62.711-.93 1.56-.93 2.544v19.538h9.726c1.239 0 2.264.492 3.074 1.478.81.985 1.216 2.134 1.216 3.447v29.553c0 1.423-.405 2.6-1.216 3.53-.81.93-1.835 1.395-3.074 1.395H4.29c-.476 0-.93-.082-1.358-.246a4.1 4.1 0 0 1-1.144-.657 4.658 4.658 0 0 1-.93-1.067 5.186 5.186 0 0 1-.643-1.395 5.566 5.566 0 0 1-.215-1.56V93.47c0-.437.048-.875.143-1.313a3.95 3.95 0 0 1 .429-1.15c.19-.328.429-.656.715-.984.286-.329.572-.602.858-.821.286-.22.62-.383 1.001-.493.382-.11.763-.164 1.144-.164h9.726V61.619c0-.985.31-1.833.93-2.544.619-.712 1.358-1.068 2.216-1.068h44.335V39.62h-9.582c-1.24 0-2.288-.492-3.146-1.477a5.09 5.09 0 0 1-1.287-3.448V5.14c0-1.423.429-2.627 1.287-3.612.858-.985 1.907-1.477 3.146-1.477h25.743c.763 0 1.478.246 2.145.739a5.17 5.17 0 0 1 1.573 1.888c.382.766.573 1.587.573 2.462v29.553c0 1.313-.43 2.463-1.287 3.448-.859.985-1.86 1.477-3.004 1.477h-9.725v18.389h42.762c.954 0 1.74.355 2.36 1.067.62.711.93 1.56.93 2.545v26.925h9.582c1.239 0 2.288.492 3.146 1.478z"/></svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -1 +0,0 @@
<svg width="130" height="130" xmlns="http://www.w3.org/2000/svg"><path d="M63.444 64.996c20.633 0 37.359-14.308 37.359-31.953 0-17.649-16.726-31.952-37.359-31.952-20.631 0-37.36 14.303-37.358 31.952 0 17.645 16.727 31.953 37.359 31.953zM80.57 75.65H49.434c-26.652 0-48.26 18.477-48.26 41.27v2.664c0 9.316 21.608 9.325 48.26 9.325H80.57c26.649 0 48.256-.344 48.256-9.325v-2.663c0-22.794-21.605-41.271-48.256-41.271z" stroke="#979797"/></svg>

Before

Width:  |  Height:  |  Size: 440 B

View File

@ -1,22 +0,0 @@
# replace default config
# multipass: true
# full: true
plugins:
# - name
#
# or:
# - name: false
# - name: true
#
# or:
# - name:
# param1: 1
# param2: 2
- removeAttrs:
attrs:
- 'fill'
- 'fill-rule'

View File

@ -1,40 +0,0 @@
<template>
<section class="app-main">
<transition name="fade-transform" mode="out-in">
<router-view :key="key" />
</transition>
</section>
</template>
<script>
export default {
name: 'AppMain',
computed: {
key() {
return this.$route.path
}
}
}
</script>
<style scoped>
.app-main {
/*50 = navbar */
min-height: calc(100vh - 30px);
width: 100%;
position: relative;
overflow: hidden;
}
.fixed-header+.app-main {
padding-top: 50px;
}
</style>
<style lang="scss">
// fix css style bug in open el-dialog
.el-popup-parent--hidden {
.fixed-header {
padding-right: 15px;
}
}
</style>

View File

@ -1,131 +0,0 @@
<template>
<div class="navbar">
<hamburger
:is-active="sidebar.opened"
class="hamburger-container"
@toggleClick="toggleSideBar"
/>
<breadcrumb class="breadcrumb-container" />
<div class="right-menu">
<el-dropdown class="avatar-container" trigger="click">
<div class="avatar-wrapper">
<!-- <img :src="avatar+'?imageView2/1/w/80/h/80'" class="user-avatar"> -->
<el-avatar size="small" :src="avatar" />&nbsp;
<span>{{ name }}</span>
<i class="el-icon-caret-bottom" />
</div>
<el-dropdown-menu slot="dropdown" class="user-dropdown">
<router-link to="/">
<el-dropdown-item> </el-dropdown-item>
</router-link>
<el-dropdown-item divided>
<span style="display:block;" @click="logout">退出登录</span>
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
import Breadcrumb from '@/components/Breadcrumb'
import Hamburger from '@/components/Hamburger'
export default {
components: {
Breadcrumb,
Hamburger
},
computed: {
...mapGetters(['sidebar', 'avatar', 'name'])
},
methods: {
toggleSideBar() {
this.$store.dispatch('app/toggleSideBar')
},
async logout() {
await this.$store.dispatch('user/logout')
this.$router.push(`/login?redirect=${this.$route.fullPath}`)
}
}
}
</script>
<style lang="scss" scoped>
.navbar {
height: 50px;
overflow: hidden;
position: relative;
background: #fff;
box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
.hamburger-container {
line-height: 46px;
height: 100%;
float: left;
cursor: pointer;
transition: background 0.3s;
-webkit-tap-highlight-color: transparent;
&:hover {
background: rgba(0, 0, 0, 0.025);
}
}
.breadcrumb-container {
float: left;
}
.right-menu {
float: right;
height: 100%;
line-height: 50px;
cursor: pointer;
&:focus {
outline: none;
}
.right-menu-item {
display: inline-block;
padding: 0 8px;
height: 100%;
font-size: 18px;
color: #5a5e66;
vertical-align: text-bottom;
&.hover-effect {
cursor: pointer;
transition: background 0.3s;
&:hover {
background: rgba(0, 0, 0, 0.025);
}
}
}
.avatar-container {
margin-right: 30px;
height: 50px;
.avatar-wrapper {
display: flex;
align-items: center;
position: relative;
.user-avatar {
cursor: pointer;
width: 40px;
height: 40px;
border-radius: 10px;
}
}
}
}
}
.w20 {
width: 20px;
font-size: 30px;
}
</style>

View File

@ -1,26 +0,0 @@
export default {
computed: {
device() {
return this.$store.state.app.device
}
},
mounted() {
// In order to fix the click on menu on the ios device will trigger the mouseleave bug
// https://github.com/PanJiaChen/vue-element-admin/issues/1135
this.fixBugIniOS()
},
methods: {
fixBugIniOS() {
const $subMenu = this.$refs.subMenu
if ($subMenu) {
const handleMouseleave = $subMenu.handleMouseleave
$subMenu.handleMouseleave = (e) => {
if (this.device === 'mobile') {
return
}
handleMouseleave(e)
}
}
}
}
}

View File

@ -1,29 +0,0 @@
<script>
export default {
name: 'MenuItem',
functional: true,
props: {
icon: {
type: String,
default: ''
},
title: {
type: String,
default: ''
}
},
render(h, context) {
const { icon, title } = context.props
const vnodes = []
if (icon) {
vnodes.push(<svg-icon icon-class={icon}/>)
}
if (title) {
vnodes.push(<span slot='title'>{(title)}</span>)
}
return vnodes
}
}
</script>

View File

@ -1,36 +0,0 @@
<template>
<!-- eslint-disable vue/require-component-is -->
<component v-bind="linkProps(to)">
<slot />
</component>
</template>
<script>
import { isExternal } from '@/utils/validate'
export default {
props: {
to: {
type: String,
required: true
}
},
methods: {
linkProps(url) {
if (isExternal(url)) {
return {
is: 'a',
href: url,
target: '_blank',
rel: 'noopener'
}
}
return {
is: 'router-link',
to: url
}
}
}
}
</script>

View File

@ -1,82 +0,0 @@
<template>
<div class="sidebar-logo-container" :class="{'collapse':collapse}">
<transition name="sidebarLogoFade">
<router-link v-if="collapse" key="collapse" class="sidebar-logo-link" to="/">
<img v-if="logo" :src="logo" class="sidebar-logo">
<h1 v-else class="sidebar-title">{{ title }} </h1>
</router-link>
<router-link v-else key="expand" class="sidebar-logo-link" to="/">
<img v-if="logo" :src="logo" class="sidebar-logo">
<h1 class="sidebar-title">{{ title }} </h1>
</router-link>
</transition>
</div>
</template>
<script>
export default {
name: 'SidebarLogo',
props: {
collapse: {
type: Boolean,
required: true
}
},
data() {
return {
title: 'Youfool Vue Template',
logo: 'favicon.ico'
}
}
}
</script>
<style lang="scss" scoped>
.sidebarLogoFade-enter-active {
transition: opacity 1.5s;
}
.sidebarLogoFade-enter,
.sidebarLogoFade-leave-to {
opacity: 0;
}
.sidebar-logo-container {
position: relative;
width: 100%;
height: 50px;
line-height: 50px;
background: #2b2f3a;
text-align: center;
overflow: hidden;
& .sidebar-logo-link {
height: 100%;
width: 100%;
& .sidebar-logo {
width: 32px;
height: 32px;
vertical-align: middle;
margin-right: 12px;
}
& .sidebar-title {
display: inline-block;
margin: 0;
color: #fff;
font-weight: 600;
line-height: 50px;
font-size: 14px;
font-family: Avenir, Helvetica Neue, Arial, Helvetica, sans-serif;
vertical-align: middle;
}
}
&.collapse {
.sidebar-logo {
margin-right: 0px;
}
}
}
</style>

View File

@ -1,95 +0,0 @@
<template>
<div v-if="!item.hidden" class="menu-wrapper">
<template v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children||onlyOneChild.noShowingChildren)&&!item.alwaysShow">
<app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path)">
<el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest}">
<item :icon="onlyOneChild.meta.icon||(item.meta&&item.meta.icon)" :title="onlyOneChild.meta.title" />
</el-menu-item>
</app-link>
</template>
<el-submenu v-else ref="subMenu" :index="resolvePath(item.path)" popper-append-to-body>
<template slot="title">
<item v-if="item.meta" :icon="item.meta && item.meta.icon" :title="item.meta.title" />
</template>
<sidebar-item
v-for="child in item.children"
:key="child.path"
:is-nest="true"
:item="child"
:base-path="resolvePath(child.path)"
class="nest-menu"
/>
</el-submenu>
</div>
</template>
<script>
import path from 'path'
import { isExternal } from '@/utils/validate'
import Item from './Item'
import AppLink from './Link'
import FixiOSBug from './FixiOSBug'
export default {
name: 'SidebarItem',
components: { Item, AppLink },
mixins: [FixiOSBug],
props: {
// route object
item: {
type: Object,
required: true
},
isNest: {
type: Boolean,
default: false
},
basePath: {
type: String,
default: ''
}
},
data() {
// To fix https://github.com/PanJiaChen/vue-admin-template/issues/237
// TODO: refactor with render function
this.onlyOneChild = null
return {}
},
methods: {
hasOneShowingChild(children = [], parent) {
const showingChildren = children.filter(item => {
if (item.hidden) {
return false
} else {
// Temp set(will be used if only has one showing child)
this.onlyOneChild = item
return true
}
})
// When there is only one child router, the child router is displayed by default
if (showingChildren.length === 1) {
return true
}
// Show parent if there are no child router to display
if (showingChildren.length === 0) {
this.onlyOneChild = { ... parent, path: '', noShowingChildren: true }
return true
}
return false
},
resolvePath(routePath) {
if (isExternal(routePath)) {
return routePath
}
if (isExternal(this.basePath)) {
return this.basePath
}
return path.resolve(this.basePath, routePath)
}
}
}
</script>

View File

@ -1,54 +0,0 @@
<template>
<div :class="{'has-logo':showLogo}">
<logo v-if="showLogo" :collapse="isCollapse" />
<el-scrollbar wrap-class="scrollbar-wrapper">
<el-menu
:default-active="activeMenu"
:collapse="isCollapse"
:background-color="variables.menuBg"
:text-color="variables.menuText"
:unique-opened="false"
:active-text-color="variables.menuActiveText"
:collapse-transition="false"
mode="vertical"
>
<sidebar-item v-for="route in permission_routes" :key="route.path" :item="route" :base-path="route.path" />
</el-menu>
</el-scrollbar>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
import Logo from './Logo'
import SidebarItem from './SidebarItem'
import variables from '@/styles/variables.scss'
export default {
components: { SidebarItem, Logo },
computed: {
...mapGetters([
'permission_routes',
'sidebar'
]),
activeMenu() {
const route = this.$route
const { meta, path } = route
// if set path, the sidebar will highlight the path you set
if (meta.activeMenu) {
return meta.activeMenu
}
return path
},
showLogo() {
return this.$store.state.settings.sidebarLogo
},
variables() {
return variables
},
isCollapse() {
return !this.sidebar.opened
}
}
}
</script>

View File

@ -1,3 +0,0 @@
export { default as Navbar } from './Navbar'
export { default as Sidebar } from './Sidebar'
export { default as AppMain } from './AppMain'

View File

@ -1,45 +0,0 @@
import store from '@/store'
const { body } = document
const WIDTH = 992 // refer to Bootstrap's responsive design
export default {
watch: {
$route(route) {
if (this.device === 'mobile' && this.sidebar.opened) {
store.dispatch('app/closeSideBar', { withoutAnimation: false })
}
}
},
beforeMount() {
window.addEventListener('resize', this.$_resizeHandler)
},
beforeDestroy() {
window.removeEventListener('resize', this.$_resizeHandler)
},
mounted() {
const isMobile = this.$_isMobile()
if (isMobile) {
store.dispatch('app/toggleDevice', 'mobile')
store.dispatch('app/closeSideBar', { withoutAnimation: true })
}
},
methods: {
// use $_ for mixins properties
// https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential
$_isMobile() {
const rect = body.getBoundingClientRect()
return rect.width - 1 < WIDTH
},
$_resizeHandler() {
if (!document.hidden) {
const isMobile = this.$_isMobile()
store.dispatch('app/toggleDevice', isMobile ? 'mobile' : 'desktop')
if (isMobile) {
store.dispatch('app/closeSideBar', { withoutAnimation: true })
}
}
}
}
}

View File

@ -1,6 +0,0 @@
import Vue from 'vue'
import Element from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import locale from 'element-ui/lib/locale/lang/zh-CN' // 中文
Vue.use(Element, { locale })

View File

@ -14,19 +14,11 @@ router.beforeEach(async (to, from, next) => {
await oauthLoginByCerno(to.query.token, to.query.cerno, to.query.tel).then((data) => {
setToken('token')
}).catch(() => {
callMessage({
type: 'error',
message: '登录失败'
})
})
} else {
await oauthLogin(to.query.token).then((data) => {
setToken('token')
}).catch(() => {
callMessage({
type: 'error',
message: '登录失败'
})
})
}
next({

View File

@ -1,16 +0,0 @@
module.exports = {
title: process.env.VUE_APP_NAME,
/**
* @type {boolean} true | false
* @description Whether fix the header
*/
fixedHeader: true,
/**
* @type {boolean} true | false
* @description Whether show the logo in sidebar
*/
sidebarLogo: true
}

View File

@ -1,29 +0,0 @@
import defaultSettings from '@/settings'
const { showSettings, fixedHeader, sidebarLogo } = defaultSettings
const state = {
showSettings: showSettings,
fixedHeader: fixedHeader,
sidebarLogo: sidebarLogo
}
const mutations = {
CHANGE_SETTING: (state, { key, value }) => {
state[key] = value
}
}
const actions = {
changeSetting({ commit }, data) {
commit('CHANGE_SETTING', data)
}
}
export default {
namespaced: true,
state,
mutations,
actions
}

View File

@ -1,44 +0,0 @@
// cover some element-ui styles
.el-breadcrumb__inner,
.el-breadcrumb__inner a {
font-weight: 400 !important;
}
.el-upload {
input[type="file"] {
display: none !important;
}
}
.el-upload__input {
display: none;
}
// to fixed https://github.com/ElemeFE/element/issues/2461
.el-dialog {
transform: none;
left: 0;
position: relative;
margin: 0 auto;
}
// refine element ui upload
.upload-container {
.el-upload {
width: 100%;
.el-upload-dragger {
width: 100%;
height: 200px;
}
}
}
// dropdown
.el-dropdown-menu {
a {
display: block
}
}

View File

@ -1,28 +0,0 @@
@mixin clearfix {
&:after {
content: "";
display: table;
clear: both;
}
}
@mixin scrollBar {
&::-webkit-scrollbar-track-piece {
background: #d3dce6;
}
&::-webkit-scrollbar {
width: 6px;
}
&::-webkit-scrollbar-thumb {
background: #99a9bf;
border-radius: 20px;
}
}
@mixin relative {
position: relative;
width: 100%;
height: 100%;
}

View File

@ -1,209 +0,0 @@
#app {
.main-container {
min-height: 100%;
transition: margin-left .28s;
margin-left: $sideBarWidth;
position: relative;
}
.sidebar-container {
transition: width 0.28s;
width: $sideBarWidth !important;
background-color: $menuBg;
height: 100%;
position: fixed;
font-size: 0px;
top: 0;
bottom: 0;
left: 0;
z-index: 1001;
overflow: hidden;
// reset element-ui css
.horizontal-collapse-transition {
transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out;
}
.scrollbar-wrapper {
overflow-x: hidden !important;
}
.el-scrollbar__bar.is-vertical {
right: 0px;
}
.el-scrollbar {
height: 100%;
}
&.has-logo {
.el-scrollbar {
height: calc(100% - 50px);
}
}
.is-horizontal {
display: none;
}
a {
display: inline-block;
width: 100%;
overflow: hidden;
}
.svg-icon {
margin-right: 16px;
}
.el-menu {
border: none;
height: 100%;
width: 100% !important;
}
// menu hover
.submenu-title-noDropdown,
.el-submenu__title {
&:hover {
background-color: $menuHover !important;
}
}
.is-active>.el-submenu__title {
color: $subMenuActiveText !important;
}
& .nest-menu .el-submenu>.el-submenu__title,
& .el-submenu .el-menu-item {
min-width: $sideBarWidth !important;
background-color: $subMenuBg !important;
&:hover {
background-color: $subMenuHover !important;
}
}
}
.hideSidebar {
.sidebar-container {
width: 54px !important;
}
.main-container {
margin-left: 54px;
}
.submenu-title-noDropdown {
padding: 0 !important;
position: relative;
.el-tooltip {
padding: 0 !important;
.svg-icon {
margin-left: 20px;
}
}
}
.el-submenu {
overflow: hidden;
&>.el-submenu__title {
padding: 0 !important;
.svg-icon {
margin-left: 20px;
}
.el-submenu__icon-arrow {
display: none;
}
}
}
.el-menu--collapse {
.el-submenu {
&>.el-submenu__title {
&>span {
height: 0;
width: 0;
overflow: hidden;
visibility: hidden;
display: inline-block;
}
}
}
}
}
.el-menu--collapse .el-menu .el-submenu {
min-width: $sideBarWidth !important;
}
// mobile responsive
.mobile {
.main-container {
margin-left: 0px;
}
.sidebar-container {
transition: transform .28s;
width: $sideBarWidth !important;
}
&.hideSidebar {
.sidebar-container {
pointer-events: none;
transition-duration: 0.3s;
transform: translate3d(-$sideBarWidth, 0, 0);
}
}
}
.withoutAnimation {
.main-container,
.sidebar-container {
transition: none;
}
}
}
// when menu collapsed
.el-menu--vertical {
&>.el-menu {
.svg-icon {
margin-right: 16px;
}
}
.nest-menu .el-submenu>.el-submenu__title,
.el-menu-item {
&:hover {
// you can use $subMenuHover
background-color: $menuHover !important;
}
}
// the scroll bar appears when the subMenu is too long
>.el-menu--popup {
max-height: 100vh;
overflow-y: auto;
&::-webkit-scrollbar-track-piece {
background: #d3dce6;
}
&::-webkit-scrollbar {
width: 6px;
}
&::-webkit-scrollbar-thumb {
background: #99a9bf;
border-radius: 20px;
}
}
}

View File

@ -1,48 +0,0 @@
// global transition css
/* fade */
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.28s;
}
.fade-enter,
.fade-leave-active {
opacity: 0;
}
/* fade-transform */
.fade-transform-leave-active,
.fade-transform-enter-active {
transition: all .5s;
}
.fade-transform-enter {
opacity: 0;
transform: translateX(-30px);
}
.fade-transform-leave-to {
opacity: 0;
transform: translateX(30px);
}
/* breadcrumb transition */
.breadcrumb-enter-active,
.breadcrumb-leave-active {
transition: all .5s;
}
.breadcrumb-enter,
.breadcrumb-leave-active {
opacity: 0;
transform: translateX(20px);
}
.breadcrumb-move {
transition: all .5s;
}
.breadcrumb-leave-active {
position: absolute;
}

View File

@ -1,37 +0,0 @@
// sidebar
//原始样式
$menuText:#bfcbd9;
$menuActiveText:#409EFF;
$subMenuActiveText:#f4f4f5; //https://github.com/ElemeFE/element/issues/12951
$menuBg:#304156;
$menuHover:#263445;
$subMenuBg:#1f2d3d;
$subMenuHover:#001528;
//亮白左菜主题
// $menuText:#595959; //一级菜单字体颜色
// $menuActiveText:#409EFF; //激活字体颜色
// $subMenuActiveText:#595959; //子级菜单字体颜色
// $menuBg:#eef1f6; //一级背景
// $menuHover:#d1dbe5;//一级hover颜色
// $subMenuBg:#e4e8f1;//子级背景
// $subMenuHover:#d1dbe5;//子级hover颜色
$sideBarWidth: 210px;//左菜单宽度
// the :export directive is the magic sauce for webpack
// https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass
:export {
menuText: $menuText;
menuActiveText: $menuActiveText;
subMenuActiveText: $subMenuActiveText;
menuBg: $menuBg;
menuHover: $menuHover;
subMenuBg: $subMenuBg;
subMenuHover: $subMenuHover;
sideBarWidth: $sideBarWidth;
}

View File

@ -1,10 +0,0 @@
import defaultSettings from '@/settings'
const title = defaultSettings.title || 'youfool-vue-template'
export default function getPageTitle(pageTitle) {
if (pageTitle) {
return `${pageTitle} - ${title}`
}
return `${title}`
}

View File

@ -1,2 +0,0 @@
/** 本文件由打包插件自动生成和修改 */
export default ''

0
src/views/Maintain.vue Normal file → Executable file
View File

View File

@ -48,11 +48,12 @@ export default {
},
methods: {
reportYear() {
if (this.$store.getters.userInfo.entBizTypeInfo?.bizInfo?.includes('GTH')) {
return showDialog({
message: '个体工商户年度报告功能暂未开放'
})
}
// 2026.03.30.cc
// if (this.$store.getters.userInfo.entBizTypeInfo?.bizInfo?.includes('GTH')) {
// return showDialog({
// message: ''
// })
// }
return annualFillBaseYearList().then((data) => {
const year = data.sort((a, b) => {
return Number(a) - Number(b)

View File

@ -1,42 +0,0 @@
<template>
<div class="dashboard-container">
<div class="dashboard-text">name: {{ name }}</div>
<div>时间{{ $moment('2018-09-19T05:54:32.767Z').format("YYYY-DD-MM HH:mm:ss") }}</div>
<div class="dashboard-text">
roles:
<span v-for="role in roles" :key="role">{{ role }}</span>
</div>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
name: 'Dashboard',
data: function() {
return {
}
},
computed: {
...mapGetters(['name', 'roles'])
}
}
</script>
<style lang="scss" scoped>
.dashboard-container {
background: $color-theme;
color: $color-classA-font-weight;
}
.dashboard {
&-container {
margin: 30px;
}
&-text {
font-size: 30px;
line-height: 46px;
}
}
</style>

View File

@ -10,7 +10,7 @@
</div>
<div class="container">
<div class="list">
<van-cell-group :border="false" title="年报(东莞">
<van-cell-group :border="false" title="年报(内蒙">
<van-cell
title="年度报告填写"
is-link
@ -34,7 +34,6 @@
/>
</van-cell-group>
<van-cell-group
v-if="!$store.getters.userInfo.userId"
:border="false"
title="信用信息信用修复"
>

View File

@ -1,254 +0,0 @@
<template>
<div class="login-container">
<el-form
ref="loginForm"
:model="loginForm"
:rules="loginRules"
class="login-form"
auto-complete="on"
label-position="left"
>
<div class="title-container">
<h3 class="title">前端开发的基础模版</h3>
</div>
<el-form-item prop="username">
<span class="svg-container">
<svg-icon icon-class="user" />
</span>
<el-input
ref="username"
v-model="loginForm.username"
placeholder="Username"
name="username"
type="text"
tabindex="1"
auto-complete="on"
/>
</el-form-item>
<el-form-item prop="password">
<span class="svg-container">
<svg-icon icon-class="password" />
</span>
<el-input
:key="passwordType"
ref="password"
v-model="loginForm.password"
:type="passwordType"
placeholder="Password"
name="password"
tabindex="2"
auto-complete="on"
@keyup.enter.native="handleLogin"
/>
<span class="show-pwd" @click="showPwd">
<svg-icon :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'" />
</span>
</el-form-item>
<el-button
:loading="loading"
type="primary"
style="width:100%;margin-bottom:30px;"
@click.native.prevent="handleLogin"
>登录</el-button>
<div class="tips">
<span style="margin-right:20px;">username: admin</span>
<span>password: any</span>
</div>
</el-form>
</div>
</template>
<script>
import { validUsername } from '@/utils/validate'
export default {
name: 'Login',
data() {
const validateUsername = (rule, value, callback) => {
if (!validUsername(value)) {
callback(new Error('Please enter the correct user name'))
} else {
callback()
}
}
const validatePassword = (rule, value, callback) => {
if (value.length < 6) {
callback(new Error('The password can not be less than 6 digits'))
} else {
callback()
}
}
return {
loginForm: {
username: 'admin',
password: '111111'
},
loginRules: {
username: [
{ required: true, trigger: 'blur', validator: validateUsername }
],
password: [
{ required: true, trigger: 'blur', validator: validatePassword }
]
},
loading: false,
passwordType: 'password',
redirect: undefined
}
},
watch: {
$route: {
handler: function(route) {
this.redirect = route.query && route.query.redirect
},
immediate: true
}
},
methods: {
showPwd() {
if (this.passwordType === 'password') {
this.passwordType = ''
} else {
this.passwordType = 'password'
}
this.$nextTick(() => {
this.$refs.password.focus()
})
},
handleLogin() {
this.$refs.loginForm.validate(valid => {
if (valid) {
this.loading = true
this.$store
.dispatch('user/login', this.loginForm)
.then(() => {
this.$router.push({ path: this.redirect || '/' })
this.loading = false
})
.catch(() => {
this.loading = false
})
} else {
console.log('error submit!!')
return false
}
})
}
}
}
</script>
<style lang="scss">
/* 修复input 背景不协调 和光标变色 */
/* Detail see https://github.com/PanJiaChen/vue-element-admin/pull/927 */
$bg: #283443;
$light_gray: #fff;
$cursor: #fff;
@supports (-webkit-mask: none) and (not (cater-color: $cursor)) {
.login-container .el-input input {
color: $cursor;
}
}
/* reset element-ui css */
.login-container {
.el-input {
display: inline-block;
height: 47px;
width: 85%;
input {
background: transparent;
border: 0px;
-webkit-appearance: none;
border-radius: 0px;
padding: 12px 5px 12px 15px;
color: $light_gray;
height: 47px;
caret-color: $cursor;
&:-webkit-autofill {
box-shadow: 0 0 0px 1000px $bg inset !important;
-webkit-text-fill-color: $cursor !important;
}
}
}
.el-form-item {
border: 1px solid rgba(255, 255, 255, 0.1);
background: rgba(0, 0, 0, 0.1);
border-radius: 5px;
color: #454545;
}
}
</style>
<style lang="scss" scoped>
$bg: #2d3a4b;
$dark_gray: #889aa4;
$light_gray: #eee;
.login-container {
min-height: 100%;
width: 100%;
background-color: $bg;
overflow: hidden;
.login-form {
position: relative;
width: 520px;
max-width: 100%;
padding: 160px 35px 0;
margin: 0 auto;
overflow: hidden;
}
.tips {
font-size: 14px;
color: #fff;
margin-bottom: 10px;
span {
&:first-of-type {
margin-right: 16px;
}
}
}
.svg-container {
padding: 6px 5px 6px 15px;
color: $dark_gray;
vertical-align: middle;
width: 30px;
display: inline-block;
}
.title-container {
position: relative;
.title {
font-size: 26px;
color: $light_gray;
margin: 0px auto 40px auto;
text-align: center;
font-weight: bold;
}
}
.show-pwd {
position: absolute;
right: 10px;
top: 7px;
font-size: 16px;
color: $dark_gray;
cursor: pointer;
user-select: none;
}
}
</style>

View File

@ -1,79 +0,0 @@
<template>
<div class="app-container">
<el-table
v-loading="listLoading"
:data="list"
element-loading-text="Loading"
border
fit
highlight-current-row
>
<el-table-column align="center" label="ID" width="95">
<template slot-scope="scope">
{{ scope.$index }}
</template>
</el-table-column>
<el-table-column label="Title">
<template slot-scope="scope">
{{ scope.row.title }}
</template>
</el-table-column>
<el-table-column label="Author" width="110" align="center">
<template slot-scope="scope">
<span>{{ scope.row.author }}</span>
</template>
</el-table-column>
<el-table-column label="Pageviews" width="110" align="center">
<template slot-scope="scope">
{{ scope.row.pageviews }}
</template>
</el-table-column>
<el-table-column class-name="status-col" label="Status" width="110" align="center">
<template slot-scope="scope">
<el-tag :type="scope.row.status | statusFilter">{{ scope.row.status }}</el-tag>
</template>
</el-table-column>
<el-table-column align="center" prop="created_at" label="Display_time" width="200">
<template slot-scope="scope">
<i class="el-icon-time" />
<span>{{ scope.row.display_time }}</span>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script>
import { getList } from '@/api/table'
export default {
filters: {
statusFilter(status) {
const statusMap = {
published: 'success',
draft: 'gray',
deleted: 'danger'
}
return statusMap[status]
}
},
data() {
return {
list: null,
listLoading: true
}
},
created() {
this.fetchData()
},
methods: {
fetchData() {
this.listLoading = true
getList().then(data => {
this.list = data.items
this.listLoading = false
})
}
}
}
</script>

View File

@ -1,169 +0,0 @@
'use strict'
const path = require('path')
const defaultSettings = require('./src/settings.js')
const IncrePack = require('./build/increpack')
const ConstantFile = require('./build/constant-file')
function resolve(dir) {
return path.join(__dirname, dir)
}
const name = defaultSettings.title || 'youfool-vue-template' // page title
// If your port is set to 80,
// use administrator privileges to execute the command line.
// For example, Mac: sudo npm run
// You can change the port by the following methods:
// port = 9528 npm run dev OR npm run dev --port = 9528
const port = process.env.port || process.env.npm_config_port || 9528 // dev port
// All configuration item explanations can be find in https://cli.vuejs.org/config/
module.exports = {
/**
* You will need to set publicPath if you plan to deploy your site under a sub path,
* for example GitHub Pages. If you plan to deploy your site to https://foo.github.io/bar/,
* then publicPath should be set to "/bar/".
* In most cases please use '/' !!!
* Detail: https://cli.vuejs.org/config/#publicpath
*/
publicPath: process.env.VUE_APP_PUBLICPATH,
outputDir: 'dist',
assetsDir: 'static',
lintOnSave: process.env.NODE_ENV === 'development',
productionSourceMap: false,
devServer: {
port: port,
open: false,
overlay: {
warnings: false,
errors: true
},
proxy: {
// change xxx-api/login => mock/login
// detail: https://cli.vuejs.org/config/#devserver-proxy
// 如果有多个mock请往里面继续添加
[process.env.VUE_APP_BASE_API + '/user']: {
target: `http://127.0.0.1:${port}/mock`,
changeOrigin: true,
pathRewrite: {
['^' + process.env.VUE_APP_BASE_API]: ''
}
},
[process.env.VUE_APP_BASE_API + '/table']: {
target: `http://127.0.0.1:${port}/mock`,
changeOrigin: true,
pathRewrite: {
['^' + process.env.VUE_APP_BASE_API]: ''
}
}
// [process.env.VUE_APP_BASE_API]: {
// target: `http://mock-api.com`,
// changeOrigin: true,
// pathRewrite: {
// ['^' + process.env.VUE_APP_BASE_API]: ''
// }
// }
}
},
configureWebpack: {
// provide the app's title in webpack's name field, so that
// it can be accessed in index.html to inject the correct title.
name: name,
resolve: {
alias: {
'@': resolve('src')
}
},
plugins: [
new IncrePack(),
new ConstantFile({ api: process.env.CMS_DICT_API })
]
},
// 引入自定义的全局样式表
css: {
loaderOptions: {
sass: {
prependData: `@import "./src/assets/css/global.scss";`
}
}
},
// 兼容浏览器
transpileDependencies: ['element-ui'],
chainWebpack(config) {
config.plugins.delete('preload') // TODO: need test
config.plugins.delete('prefetch') // TODO: need test
// set svg-sprite-loader
config.module
.rule('svg')
.exclude.add(resolve('src/icons'))
.end()
config.module
.rule('icons')
.test(/\.svg$/)
.include.add(resolve('src/icons'))
.end()
.use('svg-sprite-loader')
.loader('svg-sprite-loader')
.options({
symbolId: 'icon-[name]'
})
.end()
// set preserveWhitespace
config.module
.rule('vue')
.use('vue-loader')
.loader('vue-loader')
.tap(options => {
options.compilerOptions.preserveWhitespace = true
return options
})
.end()
config
// https://webpack.js.org/configuration/devtool/#development
.when(process.env.NODE_ENV === 'development',
config => config.devtool('cheap-source-map')
)
config
.when(process.env.NODE_ENV !== 'development',
config => {
config
.plugin('ScriptExtHtmlWebpackPlugin')
.after('html')
.use('script-ext-html-webpack-plugin', [{
// `runtime` must same as runtimeChunk name. default is `runtime`
inline: /runtime\..*\.js$/
}])
.end()
config
.optimization.splitChunks({
chunks: 'all',
cacheGroups: {
libs: {
name: 'chunk-libs',
test: /[\\/]node_modules[\\/]/,
priority: 10,
chunks: 'initial' // only package third parties that are initially dependent
},
elementUI: {
name: 'chunk-elementUI', // split elementUI into a single package
priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app
test: /[\\/]node_modules[\\/]_?element-ui(.*)/ // in order to adapt to cnpm
},
commons: {
name: 'chunk-commons',
test: resolve('src/components'), // can customize your rules
minChunks: 3, // minimum common number
priority: 5,
reuseExistingChunk: true
}
}
})
config.optimization.runtimeChunk('single')
}
)
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB