mirror of
https://gitee.com/log4j/pig-ui.git
synced 2024-12-22 21:22:33 +08:00
'admin-21.06.29:更新最新依赖、各项优化,请查看CHANGELOG.md更新文件'
This commit is contained in:
parent
92904ffef3
commit
b2fd7d6010
11
CHANGELOG.md
11
CHANGELOG.md
@ -2,6 +2,17 @@
|
||||
|
||||
🎉🎉🔥 `vue-next-admin` 基于 vue3.x 、Typescript、vite、Element plus 等,适配手机、平板、pc 的后台开源免费模板库(vue2.x 请切换 vue-prev-admin 分支)
|
||||
|
||||
## 1.0.8
|
||||
|
||||
`2021.06.29`
|
||||
|
||||
- 🌟 更新 依赖更新最新版本
|
||||
- 🎉 新增 表单中英文切换演示
|
||||
- 🎯 优化 登录页查看密码 icon 图标
|
||||
- 🎯 优化 图标选择器
|
||||
- 🎯 优化 拖动指令
|
||||
- 🐞 修复 form 表单在页面小于 576px 时的排版问题
|
||||
|
||||
## 1.0.7
|
||||
|
||||
`2021.06.24`
|
||||
|
16
package.json
16
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "vue-next-admin",
|
||||
"version": "1.0.7",
|
||||
"version": "1.0.8",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
@ -13,7 +13,7 @@
|
||||
"cropperjs": "^1.5.12",
|
||||
"echarts": "^5.1.2",
|
||||
"echarts-wordcloud": "^2.0.0",
|
||||
"element-plus": "^1.0.2-beta.51",
|
||||
"element-plus": "^1.0.2-beta.53",
|
||||
"mitt": "^3.0.0",
|
||||
"nprogress": "^0.2.0",
|
||||
"print-js": "^1.6.0",
|
||||
@ -32,17 +32,17 @@
|
||||
"devDependencies": {
|
||||
"@types/axios": "^0.14.0",
|
||||
"@types/clipboard": "^2.0.1",
|
||||
"@types/node": "^15.12.4",
|
||||
"@types/node": "^15.12.5",
|
||||
"@types/nprogress": "^0.2.0",
|
||||
"@types/sortablejs": "^1.10.6",
|
||||
"@typescript-eslint/eslint-plugin": "^4.28.0",
|
||||
"@typescript-eslint/parser": "^4.28.0",
|
||||
"@vitejs/plugin-vue": "^1.2.3",
|
||||
"@typescript-eslint/eslint-plugin": "^4.28.1",
|
||||
"@typescript-eslint/parser": "^4.28.1",
|
||||
"@vitejs/plugin-vue": "^1.2.4",
|
||||
"@vue/compiler-sfc": "^3.1.2",
|
||||
"dotenv": "^10.0.0",
|
||||
"eslint": "^7.29.0",
|
||||
"eslint-plugin-vue": "^7.11.1",
|
||||
"prettier": "^2.3.1",
|
||||
"eslint-plugin-vue": "^7.12.1",
|
||||
"prettier": "^2.3.2",
|
||||
"sass": "^1.35.1",
|
||||
"sass-loader": "^12.1.0",
|
||||
"typescript": "^4.3.4",
|
||||
|
@ -1,57 +1,49 @@
|
||||
<template>
|
||||
<div class="icon-selector">
|
||||
<el-popover :placement="placement" :width="fontIconWidth" v-model:visible="fontIconVisible" popper-class="icon-selector-popper">
|
||||
<el-popover placement="bottom" :width="fontIconWidth" v-model:visible="fontIconVisible" popper-class="icon-selector-popper">
|
||||
<template #reference>
|
||||
<el-input
|
||||
v-model="fontIcon"
|
||||
placeholder="请点击选择图标"
|
||||
clearable
|
||||
size="small"
|
||||
v-model="fontIconSearch"
|
||||
:placeholder="placeholder"
|
||||
:clearable="clearable"
|
||||
:disabled="disabled"
|
||||
:size="size"
|
||||
ref="inputWidthRef"
|
||||
:prefix-icon="fontIconPrefix"
|
||||
@clear="onClearFontIcon"
|
||||
></el-input>
|
||||
>
|
||||
<template #prepend>
|
||||
<i :class="fontIconPrefix === '' ? prepend : fontIconPrefix" class="font14"></i>
|
||||
</template>
|
||||
</el-input>
|
||||
</template>
|
||||
<transition name="el-zoom-in-top">
|
||||
<div class="icon-selector-warp" v-show="fontIconVisible">
|
||||
<div class="icon-selector-warp-title">请选择一个图标</div>
|
||||
<div v-if="isAllOn" class="icon-selector-all">
|
||||
<el-input v-model="fontIconSearch" placeholder="请输入内容进行搜索" size="small"></el-input>
|
||||
<div class="icon-selector-all-tabs">
|
||||
<div
|
||||
class="icon-selector-all-tabs-item"
|
||||
v-for="(v, k) in fontIconTabsList"
|
||||
:key="k"
|
||||
@click="onFontIconTabsClick(v, k)"
|
||||
:class="{ 'icon-selector-all-tabs-active': fontIconTabsIndex === k }"
|
||||
>
|
||||
<div class="label">{{ v.label }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="icon-selector-warp-title">{{ title }}</div>
|
||||
<div class="icon-selector-warp-row">
|
||||
<el-row :gutter="10">
|
||||
<el-col
|
||||
:xs="4"
|
||||
:sm="4"
|
||||
:md="2"
|
||||
:lg="2"
|
||||
:xl="1"
|
||||
:class="`${fontIconTabsIcon}-col`"
|
||||
@click="onColClick(v, k)"
|
||||
v-for="(v, k) in fontIconSheetsFilterList"
|
||||
:key="k"
|
||||
>
|
||||
<div class="icon-selector-warp-item" :class="{ 'icon-selector-active': fontIconIndex === k }">
|
||||
<div class="flex-margin">
|
||||
<div class="icon-selector-warp-item-value">
|
||||
<i :class="[fontIconTabsIcon, v]"></i>
|
||||
<el-scrollbar>
|
||||
<el-row :gutter="10">
|
||||
<el-col
|
||||
:xs="4"
|
||||
:sm="4"
|
||||
:md="2"
|
||||
:lg="2"
|
||||
:xl="1"
|
||||
:class="`${fontIconTabsIcon}-col`"
|
||||
@click="onColClick(v, k)"
|
||||
v-for="(v, k) in fontIconSheetsFilterList"
|
||||
:key="k"
|
||||
>
|
||||
<div class="icon-selector-warp-item" :class="{ 'icon-selector-active': fontIconIndex === k }">
|
||||
<div class="flex-margin">
|
||||
<div class="icon-selector-warp-item-value">
|
||||
<i :class="[fontIconTabsIcon, v]"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-empty :image-size="100" v-if="fontIconSheetsFilterList.length <= 0"></el-empty>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-empty :image-size="100" v-if="fontIconSheetsFilterList.length <= 0" :description="emptyDescription"></el-empty>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
@ -65,21 +57,50 @@ import initIconfont from '/@/utils/getStyleSheets';
|
||||
export default {
|
||||
name: 'iconSelector',
|
||||
props: {
|
||||
// 是否开启高级功能
|
||||
isAllOn: {
|
||||
// 输入框前置内容
|
||||
prepend: {
|
||||
type: String,
|
||||
default: () => 'el-icon-thumb',
|
||||
},
|
||||
// 输入框占位文本
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: () => '请输入内容搜索图标或者选择图标',
|
||||
},
|
||||
// 输入框占位文本
|
||||
size: {
|
||||
type: String,
|
||||
default: () => 'small',
|
||||
},
|
||||
// 弹窗标题
|
||||
title: {
|
||||
type: String,
|
||||
default: () => '请选择图标',
|
||||
},
|
||||
// icon 图标类型
|
||||
type: {
|
||||
type: String,
|
||||
default: () => 'ele',
|
||||
},
|
||||
// 禁用
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: () => false,
|
||||
},
|
||||
// 出现位置
|
||||
placement: {
|
||||
// 是否可清空
|
||||
clearable: {
|
||||
type: Boolean,
|
||||
default: () => true,
|
||||
},
|
||||
// 自定义空状态描述文字
|
||||
emptyDescription: {
|
||||
type: String,
|
||||
default: () => 'bottom',
|
||||
default: () => '无相关图标',
|
||||
},
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
const inputWidthRef = ref();
|
||||
const state: any = reactive({
|
||||
fontIcon: '',
|
||||
fontIconPrefix: '',
|
||||
fontIconVisible: false,
|
||||
fontIconWidth: 0,
|
||||
@ -87,11 +108,7 @@ export default {
|
||||
fontIconSearch: '',
|
||||
fontIconTabsIndex: 0,
|
||||
fontIconTabsIcon: 'iconfont ali',
|
||||
fontIconTabsList: [{ label: 'iconfont' }, { label: 'element' }, { label: 'awesome' }],
|
||||
fontIconSheetsList: [],
|
||||
fontIconSheetsListAli: [],
|
||||
fontIconSheetsListEle: [],
|
||||
fontIconSheetsListAwe: [],
|
||||
});
|
||||
// 设置无数据时的空状态
|
||||
const fontIconSheetsFilterList = computed(() => {
|
||||
@ -115,42 +132,40 @@ export default {
|
||||
};
|
||||
// 初始化数据
|
||||
const initFontIconData = () => {
|
||||
initIconfont.ali().then((res: any) => {
|
||||
state.fontIconSheetsList = res;
|
||||
state.fontIconSheetsListAli = res;
|
||||
});
|
||||
initIconfont.ele().then((res: any) => {
|
||||
state.fontIconSheetsListEle = res;
|
||||
});
|
||||
initIconfont.awe().then((res: any) => {
|
||||
state.fontIconSheetsListAwe = res;
|
||||
});
|
||||
if (props.type === 'ali') {
|
||||
initIconfont.ali().then((res: any) => {
|
||||
state.fontIconTabsIcon = 'iconfont ali';
|
||||
state.fontIconTabsIndex = 0;
|
||||
state.fontIconSheetsList = res;
|
||||
});
|
||||
} else if (props.type === 'ele') {
|
||||
initIconfont.ele().then((res: any) => {
|
||||
state.fontIconTabsIcon = 'ele';
|
||||
state.fontIconTabsIndex = 1;
|
||||
state.fontIconSheetsList = res;
|
||||
});
|
||||
} else if (props.type === 'awe') {
|
||||
initIconfont.awe().then((res: any) => {
|
||||
state.fontIconTabsIcon = 'fa awe';
|
||||
state.fontIconTabsIndex = 2;
|
||||
state.fontIconSheetsList = res;
|
||||
});
|
||||
}
|
||||
};
|
||||
// 当前项点击
|
||||
// 获取当前点击的 icon 图标
|
||||
const onColClick = (v: any, k: number) => {
|
||||
state.fontIconIndex = k;
|
||||
state.fontIcon = v;
|
||||
state.fontIconVisible = false;
|
||||
if (state.fontIconTabsIndex === 0) state.fontIconPrefix = `iconfont ali ${v}`;
|
||||
else if (state.fontIconTabsIndex === 1) state.fontIconPrefix = `ele ${v}`;
|
||||
else if (state.fontIconTabsIndex === 2) state.fontIconPrefix = `fa awe ${v}`;
|
||||
emit('get', state.fontIconPrefix);
|
||||
};
|
||||
// input 点击清除按钮时
|
||||
// 清空当前点击的 icon 图标
|
||||
const onClearFontIcon = () => {
|
||||
state.fontIconIndex = '';
|
||||
state.fontIconPrefix = '';
|
||||
emit('get', state.fontIconPrefix);
|
||||
};
|
||||
// tabs 点击
|
||||
const onFontIconTabsClick = (v: any, k: number) => {
|
||||
state.fontIconTabsIndex = k;
|
||||
if (v.label === 'iconfont') state.fontIconSheetsList = state.fontIconSheetsListAli;
|
||||
else if (v.label === 'element') state.fontIconSheetsList = state.fontIconSheetsListEle;
|
||||
else if (v.label === 'awesome') state.fontIconSheetsList = state.fontIconSheetsListAwe;
|
||||
if (k === 0) state.fontIconTabsIcon = `iconfont ali`;
|
||||
else if (k === 1) state.fontIconTabsIcon = `ele`;
|
||||
else if (k === 2) state.fontIconTabsIcon = `fa awe`;
|
||||
emit('clear', state.fontIconPrefix);
|
||||
};
|
||||
// 页面加载时
|
||||
onMounted(() => {
|
||||
@ -163,7 +178,6 @@ export default {
|
||||
fontIconSheetsFilterList,
|
||||
onColClick,
|
||||
onClearFontIcon,
|
||||
onFontIconTabsClick,
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
|
@ -14,6 +14,9 @@ import pagesHomeZhtw from '/@/i18n/pages/home/zh-tw';
|
||||
import pagesLoginZhcn from '/@/i18n/pages/login/zh-cn';
|
||||
import pagesLoginEn from '/@/i18n/pages/login/en';
|
||||
import pagesLoginZhtw from '/@/i18n/pages/login/zh-tw';
|
||||
import pagesFormI18nZhcn from '/@/i18n/pages/formI18n/zh-cn';
|
||||
import pagesFormI18nEn from '/@/i18n/pages/formI18n/en';
|
||||
import pagesFormI18nZhtw from '/@/i18n/pages/formI18n/zh-tw';
|
||||
|
||||
// 定义语言国际化内容
|
||||
/**
|
||||
@ -28,6 +31,7 @@ const messages = {
|
||||
...nextZhcn,
|
||||
...pagesHomeZhcn,
|
||||
...pagesLoginZhcn,
|
||||
...pagesFormI18nZhcn,
|
||||
},
|
||||
},
|
||||
[enLocale.name]: {
|
||||
@ -36,6 +40,7 @@ const messages = {
|
||||
...nextEn,
|
||||
...pagesHomeEn,
|
||||
...pagesLoginEn,
|
||||
...pagesFormI18nEn,
|
||||
},
|
||||
},
|
||||
[zhtwLocale.name]: {
|
||||
@ -44,6 +49,7 @@ const messages = {
|
||||
...nextZhtw,
|
||||
...pagesHomeZhtw,
|
||||
...pagesLoginZhtw,
|
||||
...pagesFormI18nZhtw,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -42,6 +42,7 @@ export default {
|
||||
pagesAwesome: 'awesome icon',
|
||||
pagesCityLinkage: 'CityLinkage',
|
||||
pagesFormAdapt: 'FormAdapt',
|
||||
pagesFormI18n: 'FormI18n',
|
||||
pagesListAdapt: 'ListAdapt',
|
||||
pagesWaterfall: 'Waterfall',
|
||||
pagesSteps: 'Steps',
|
||||
|
@ -42,6 +42,7 @@ export default {
|
||||
pagesAwesome: 'awesome 字体图标',
|
||||
pagesCityLinkage: '城市多级联动',
|
||||
pagesFormAdapt: '表单自适应',
|
||||
pagesFormI18n: '表单国际化',
|
||||
pagesListAdapt: '列表自适应',
|
||||
pagesWaterfall: '瀑布屏',
|
||||
pagesSteps: '步骤条',
|
||||
|
@ -42,6 +42,7 @@ export default {
|
||||
pagesAwesome: 'awesome 字體圖標',
|
||||
pagesCityLinkage: '都市多級聯動',
|
||||
pagesFormAdapt: '表單自我調整',
|
||||
pagesFormI18n: '表單國際化',
|
||||
pagesListAdapt: '清單自我調整',
|
||||
pagesWaterfall: '瀑布屏',
|
||||
pagesSteps: '步驟條',
|
||||
|
13
src/i18n/pages/formI18n/en.ts
Normal file
13
src/i18n/pages/formI18n/en.ts
Normal file
@ -0,0 +1,13 @@
|
||||
// 定义内容
|
||||
export default {
|
||||
formI18nLabel: {
|
||||
name: 'name',
|
||||
email: 'email',
|
||||
autograph: 'autograph',
|
||||
},
|
||||
formI18nPlaceholder: {
|
||||
name: 'Please enter your name',
|
||||
email: 'Please enter the users Department',
|
||||
autograph: 'Please enter the login account name',
|
||||
},
|
||||
};
|
13
src/i18n/pages/formI18n/zh-cn.ts
Normal file
13
src/i18n/pages/formI18n/zh-cn.ts
Normal file
@ -0,0 +1,13 @@
|
||||
// 定义内容
|
||||
export default {
|
||||
formI18nLabel: {
|
||||
name: '姓名',
|
||||
email: '用户归属部门',
|
||||
autograph: '登陆账户名',
|
||||
},
|
||||
formI18nPlaceholder: {
|
||||
name: '请输入姓名',
|
||||
email: '请输入用户归属部门',
|
||||
autograph: '请输入登陆账户名',
|
||||
},
|
||||
};
|
13
src/i18n/pages/formI18n/zh-tw.ts
Normal file
13
src/i18n/pages/formI18n/zh-tw.ts
Normal file
@ -0,0 +1,13 @@
|
||||
// 定义内容
|
||||
export default {
|
||||
formI18nLabel: {
|
||||
name: '姓名',
|
||||
email: '用戶歸屬部門',
|
||||
autograph: '登入帳戶名',
|
||||
},
|
||||
formI18nPlaceholder: {
|
||||
name: '請輸入姓名',
|
||||
email: '請輸入用戶歸屬部門',
|
||||
autograph: '請輸入登入帳戶名',
|
||||
},
|
||||
};
|
@ -665,6 +665,21 @@ export const dynamicRoutes: Array<RouteRecordRaw> = [
|
||||
icon: 'iconfont icon-biaodan',
|
||||
},
|
||||
},
|
||||
{
|
||||
path: '/pages/formI18n',
|
||||
name: 'pagesFormI18n',
|
||||
component: () => import('/@/views/pages/formI18n/index.vue'),
|
||||
meta: {
|
||||
title: 'message.router.pagesFormI18n',
|
||||
isLink: '',
|
||||
isHide: false,
|
||||
isKeepAlive: true,
|
||||
isAffix: false,
|
||||
isIframe: false,
|
||||
auth: ['admin', 'test'],
|
||||
icon: 'iconfont icon-diqiu',
|
||||
},
|
||||
},
|
||||
{
|
||||
path: '/pages/listAdapt',
|
||||
name: 'pagesListAdapt',
|
||||
|
@ -940,7 +940,7 @@
|
||||
}
|
||||
}
|
||||
.el-dialog__body {
|
||||
max-height: 70vh !important;
|
||||
max-height: calc(90vh - 111px) !important;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
@ -3,16 +3,23 @@
|
||||
.icon-selector-popper {
|
||||
padding: 0 !important;
|
||||
.icon-selector-warp {
|
||||
height: 300px;
|
||||
overflow: hidden;
|
||||
.icon-selector-warp-title {
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
padding: 0 15px;
|
||||
}
|
||||
.icon-selector-warp-row {
|
||||
max-height: 260px;
|
||||
overflow-y: auto;
|
||||
padding: 15px 15px 5px;
|
||||
height: 260px;
|
||||
overflow: hidden;
|
||||
border-top: 1px solid #ebeef5;
|
||||
.el-row {
|
||||
padding: 15px;
|
||||
}
|
||||
.el-scrollbar__bar.is-horizontal {
|
||||
display: none;
|
||||
}
|
||||
.ele-col:nth-last-child(1),
|
||||
.ele-col:nth-last-child(2) {
|
||||
display: none;
|
||||
@ -26,28 +33,26 @@
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
margin-bottom: 10px;
|
||||
transition: all 0.3s ease;
|
||||
.icon-selector-warp-item-value {
|
||||
transition: all 0.3s ease;
|
||||
i {
|
||||
font-size: 20px;
|
||||
color: #606266;
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
border: 1px solid var(--color-primary);
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
background-color: var(--color-primary-light-9);
|
||||
border: 1px solid var(--color-primary-light-6);
|
||||
.icon-selector-warp-item-value {
|
||||
i {
|
||||
color: var(--color-primary);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.icon-selector-active {
|
||||
border: 1px solid var(--color-primary);
|
||||
background-color: var(--color-primary-light-9);
|
||||
border: 1px solid var(--color-primary-light-6);
|
||||
.icon-selector-warp-item-value {
|
||||
i {
|
||||
color: var(--color-primary);
|
||||
@ -55,33 +60,5 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.icon-selector-all {
|
||||
.el-input {
|
||||
padding: 0 15px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
&-tabs {
|
||||
display: flex;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
padding: 0 15px;
|
||||
margin-bottom: 5px;
|
||||
&-item {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
color: var(--color-primary);
|
||||
}
|
||||
}
|
||||
&-active {
|
||||
background: var(--color-primary);
|
||||
border-radius: 5px;
|
||||
.label {
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,4 +10,7 @@
|
||||
.el-form-item__content {
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
.el-form-item {
|
||||
display: unset !important;
|
||||
}
|
||||
}
|
||||
|
@ -64,21 +64,16 @@ export function dragDirective(app: App) {
|
||||
app.directive('drag', {
|
||||
mounted(el, binding) {
|
||||
if (!binding.value) return false;
|
||||
|
||||
const dragDom = document.querySelector(binding.value[0]) as HTMLElement;
|
||||
const dragHeader = document.querySelector(binding.value[1]) as HTMLElement;
|
||||
|
||||
dragHeader.onmouseover = () => (dragHeader.style.cursor = `move`);
|
||||
|
||||
/**
|
||||
* pc端,哪个大佬优化下,谢谢!
|
||||
* onmousedown 鼠标按下触发事件
|
||||
* onmousemove 鼠标按下时持续触发事件
|
||||
* onmouseup 鼠标抬起触发事件
|
||||
*/
|
||||
dragHeader.onmousedown = (e) => {
|
||||
function down(e: any, type: string) {
|
||||
// 鼠标按下,计算当前元素距离可视区的距离
|
||||
const disX = e.clientX - dragHeader.offsetLeft;
|
||||
const disY = e.clientY - dragHeader.offsetTop;
|
||||
const disX = type === 'pc' ? e.clientX - dragHeader.offsetLeft : e.touches[0].clientX - dragHeader.offsetLeft;
|
||||
const disY = type === 'pc' ? e.clientY - dragHeader.offsetTop : e.touches[0].clientY - dragHeader.offsetTop;
|
||||
|
||||
// body当前宽度
|
||||
const screenWidth = document.body.clientWidth;
|
||||
@ -109,28 +104,53 @@ export function dragDirective(app: App) {
|
||||
styT = +styT.replace(/\px/g, '');
|
||||
}
|
||||
|
||||
document.onmousemove = (e) => {
|
||||
// 通过事件委托,计算移动的距离
|
||||
let left = e.clientX - disX;
|
||||
let top = e.clientY - disY;
|
||||
|
||||
// 边界处理
|
||||
if (-left > minDragDomLeft) {
|
||||
left = -minDragDomLeft;
|
||||
} else if (left > maxDragDomLeft) {
|
||||
left = maxDragDomLeft;
|
||||
}
|
||||
|
||||
if (-top > minDragDomTop) {
|
||||
top = -minDragDomTop;
|
||||
} else if (top > maxDragDomTop) {
|
||||
top = maxDragDomTop;
|
||||
}
|
||||
|
||||
// 移动当前元素
|
||||
dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`;
|
||||
return {
|
||||
disX,
|
||||
disY,
|
||||
minDragDomLeft,
|
||||
maxDragDomLeft,
|
||||
minDragDomTop,
|
||||
maxDragDomTop,
|
||||
styL,
|
||||
styT,
|
||||
};
|
||||
}
|
||||
|
||||
function move(e: any, type: string, obj: any) {
|
||||
let { disX, disY, minDragDomLeft, maxDragDomLeft, minDragDomTop, maxDragDomTop, styL, styT } = obj;
|
||||
|
||||
// 通过事件委托,计算移动的距离
|
||||
let left = type === 'pc' ? e.clientX - disX : e.touches[0].clientX - disX;
|
||||
let top = type === 'pc' ? e.clientY - disY : e.touches[0].clientY - disY;
|
||||
|
||||
// 边界处理
|
||||
if (-left > minDragDomLeft) {
|
||||
left = -minDragDomLeft;
|
||||
} else if (left > maxDragDomLeft) {
|
||||
left = maxDragDomLeft;
|
||||
}
|
||||
|
||||
if (-top > minDragDomTop) {
|
||||
top = -minDragDomTop;
|
||||
} else if (top > maxDragDomTop) {
|
||||
top = maxDragDomTop;
|
||||
}
|
||||
|
||||
// 移动当前元素
|
||||
dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`;
|
||||
}
|
||||
|
||||
/**
|
||||
* pc端
|
||||
* onmousedown 鼠标按下触发事件
|
||||
* onmousemove 鼠标按下时持续触发事件
|
||||
* onmouseup 鼠标抬起触发事件
|
||||
*/
|
||||
dragHeader.onmousedown = (e) => {
|
||||
const obj = down(e, 'pc');
|
||||
document.onmousemove = (e) => {
|
||||
move(e, 'pc', obj);
|
||||
};
|
||||
document.onmouseup = () => {
|
||||
document.onmousemove = null;
|
||||
document.onmouseup = null;
|
||||
@ -138,67 +158,16 @@ export function dragDirective(app: App) {
|
||||
};
|
||||
|
||||
/**
|
||||
* 移动端,哪个大佬优化下,谢谢!
|
||||
* 移动端
|
||||
* ontouchstart 当按下手指时,触发ontouchstart
|
||||
* ontouchmove 当移动手指时,触发ontouchmove
|
||||
* ontouchend 当移走手指时,触发ontouchend
|
||||
*/
|
||||
dragHeader.ontouchstart = (e) => {
|
||||
// 鼠标按下,计算当前元素距离可视区的距离
|
||||
const disX = e.touches[0].clientX - dragHeader.offsetLeft;
|
||||
const disY = e.touches[0].clientY - dragHeader.offsetTop;
|
||||
|
||||
// body当前宽度
|
||||
const screenWidth = document.body.clientWidth;
|
||||
// 可见区域高度(应为body高度,可某些环境下无法获取)
|
||||
const screenHeight = document.documentElement.clientHeight;
|
||||
|
||||
// 对话框宽度
|
||||
const dragDomWidth = dragDom.offsetWidth;
|
||||
// 对话框高度
|
||||
const dragDomheight = dragDom.offsetHeight;
|
||||
|
||||
const minDragDomLeft = dragDom.offsetLeft;
|
||||
const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth;
|
||||
|
||||
const minDragDomTop = dragDom.offsetTop;
|
||||
const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomheight;
|
||||
|
||||
// 获取到的值带px 正则匹配替换
|
||||
let styL: any = getComputedStyle(dragDom).left;
|
||||
let styT: any = getComputedStyle(dragDom).top;
|
||||
|
||||
// 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px
|
||||
if (styL.includes('%')) {
|
||||
styL = +document.body.clientWidth * (+styL.replace(/\%/g, '') / 100);
|
||||
styT = +document.body.clientHeight * (+styT.replace(/\%/g, '') / 100);
|
||||
} else {
|
||||
styL = +styL.replace(/\px/g, '');
|
||||
styT = +styT.replace(/\px/g, '');
|
||||
}
|
||||
|
||||
const obj = down(e, 'app');
|
||||
document.ontouchmove = (e) => {
|
||||
// 通过事件委托,计算移动的距离
|
||||
let left = e.touches[0].clientX - disX;
|
||||
let top = e.touches[0].clientY - disY;
|
||||
|
||||
// 边界处理
|
||||
if (-left > minDragDomLeft) {
|
||||
left = -minDragDomLeft;
|
||||
} else if (left > maxDragDomLeft) {
|
||||
left = maxDragDomLeft;
|
||||
}
|
||||
|
||||
if (-top > minDragDomTop) {
|
||||
top = -minDragDomTop;
|
||||
} else if (top > maxDragDomTop) {
|
||||
top = maxDragDomTop;
|
||||
}
|
||||
|
||||
// 移动当前元素
|
||||
dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`;
|
||||
move(e, 'app', obj);
|
||||
};
|
||||
|
||||
document.ontouchend = () => {
|
||||
document.ontouchmove = null;
|
||||
document.ontouchend = null;
|
||||
|
@ -1,6 +1,6 @@
|
||||
// 字体图标 url
|
||||
const cssCdnUrlList: Array<string> = [
|
||||
'//at.alicdn.com/t/font_2298093_ysc3z187xhh.css',
|
||||
'//at.alicdn.com/t/font_2298093_wl7t9plo8fs.css',
|
||||
'//netdna.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css',
|
||||
];
|
||||
// 第三方 js url
|
||||
|
@ -1,30 +1,124 @@
|
||||
<template>
|
||||
<div class="selector-container">
|
||||
<el-card shadow="hover" header="1、图标选择器(宽度自动):简单版本">
|
||||
<IconSelector @get="ongetCurrentIcon" />
|
||||
<el-card shadow="hover" header="图标选择器(宽度自动):简单版本">
|
||||
<IconSelector @get="onGetIcon" @clear="onClearIcon" />
|
||||
</el-card>
|
||||
<el-card shadow="hover" header="2、图标选择器(宽度自动):高级版本" class="mt15">
|
||||
<IconSelector @get="ongetCurrentIcon" :isAllOn="true" />
|
||||
|
||||
<el-card shadow="hover" header="图标选择器(宽度自动):参数" class="mt15">
|
||||
<el-table :data="tableData" style="width: 100%">
|
||||
<el-table-column prop="a1" label="参数"> </el-table-column>
|
||||
<el-table-column prop="a2" label="说明"> </el-table-column>
|
||||
<el-table-column prop="a3" label="类型"> </el-table-column>
|
||||
<el-table-column prop="a4" label="可选值"> </el-table-column>
|
||||
<el-table-column prop="a5" label="默认值"> </el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
|
||||
<el-card shadow="hover" header="图标选择器(宽度自动):事件" class="mt15">
|
||||
<el-table :data="tableData1" style="width: 100%">
|
||||
<el-table-column prop="a1" label="事件名称"> </el-table-column>
|
||||
<el-table-column prop="a2" label="说明"> </el-table-column>
|
||||
<el-table-column prop="a3" label="类型"> </el-table-column>
|
||||
<el-table-column prop="a4" label="回调参数"> </el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { toRefs, reactive } from 'vue';
|
||||
import { toRefs, reactive, defineComponent } from 'vue';
|
||||
import IconSelector from '/@/components/iconSelector/index.vue';
|
||||
export default {
|
||||
export default defineComponent({
|
||||
name: 'funSelector',
|
||||
components: { IconSelector },
|
||||
setup() {
|
||||
const state = reactive({});
|
||||
const state = reactive({
|
||||
tableData: [
|
||||
{
|
||||
a1: 'prepend',
|
||||
a2: '输入框前置内容,只能字体图标',
|
||||
a3: 'string',
|
||||
a4: '',
|
||||
a5: 'el-icon-thumb',
|
||||
},
|
||||
{
|
||||
a1: 'placeholder',
|
||||
a2: '输入框占位文本',
|
||||
a3: 'string',
|
||||
a4: '',
|
||||
a5: '请输入内容搜索图标或者选择图标',
|
||||
},
|
||||
{
|
||||
a1: 'size',
|
||||
a2: '尺寸',
|
||||
a3: 'string',
|
||||
a4: 'medium / small / mini',
|
||||
a5: 'small',
|
||||
},
|
||||
{
|
||||
a1: 'title',
|
||||
a2: '弹窗标题',
|
||||
a3: 'string',
|
||||
a4: '',
|
||||
a5: '请选择图标',
|
||||
},
|
||||
{
|
||||
a1: 'type',
|
||||
a2: 'icon 图标类型',
|
||||
a3: 'string',
|
||||
a4: 'ali / ele / awe',
|
||||
a5: 'ele',
|
||||
},
|
||||
{
|
||||
a1: 'disabled',
|
||||
a2: '禁用',
|
||||
a3: 'boolean',
|
||||
a4: 'true',
|
||||
a5: 'false',
|
||||
},
|
||||
{
|
||||
a1: 'clearable',
|
||||
a2: '是否可清空',
|
||||
a3: 'boolean',
|
||||
a4: 'false',
|
||||
a5: 'true',
|
||||
},
|
||||
{
|
||||
a1: 'emptyDescription',
|
||||
a2: '自定义空状态描述文字',
|
||||
a3: 'String',
|
||||
a4: '',
|
||||
a5: '无相关图标',
|
||||
},
|
||||
],
|
||||
tableData1: [
|
||||
{
|
||||
a1: 'get',
|
||||
a2: '获取当前点击的 icon 图标',
|
||||
a3: 'function',
|
||||
a4: '(icon: string)',
|
||||
},
|
||||
{
|
||||
a1: 'clear',
|
||||
a2: '清空当前点击的 icon 图标',
|
||||
a3: 'function',
|
||||
a4: '(icon: string)',
|
||||
},
|
||||
],
|
||||
});
|
||||
// 获取当前点击的 icon 图标
|
||||
const ongetCurrentIcon = (v: string) => {
|
||||
console.log(v);
|
||||
const onGetIcon = (icon: string) => {
|
||||
console.log(icon);
|
||||
};
|
||||
// 清空当前点击的 icon 图标
|
||||
const onClearIcon = (icon: string) => {
|
||||
console.log(icon);
|
||||
};
|
||||
return {
|
||||
ongetCurrentIcon,
|
||||
onGetIcon,
|
||||
onClearIcon,
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="fun-tagsview">
|
||||
<el-card shadow="hover" header="tagsView 非当前页演示">
|
||||
<el-form :model="formInline" size="small" label-width="40px" class="tags-view-form">
|
||||
<el-row :gutter="35">
|
||||
@ -16,7 +16,7 @@
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="8" :md="8" :lg="6" :xl="4">
|
||||
<el-form-item>
|
||||
<el-form-item class="fun-tagsview-from-item">
|
||||
<el-button type="primary" @click="onImplementClick" icon="el-icon-thumb">点击执行</el-button>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
@ -146,3 +146,13 @@ export default {
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.fun-tagsview {
|
||||
.fun-tagsview-from-item {
|
||||
::v-deep(.el-form-item__content) {
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -13,13 +13,20 @@
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-input
|
||||
type="password"
|
||||
:type="isShowPassword ? 'text' : 'password'"
|
||||
:placeholder="$t('message.account.accountPlaceholder2')"
|
||||
prefix-icon="el-icon-lock"
|
||||
v-model="ruleForm.password"
|
||||
autocomplete="off"
|
||||
show-password
|
||||
>
|
||||
<template #suffix>
|
||||
<i
|
||||
class="iconfont el-input__icon login-content-password"
|
||||
:class="isShowPassword ? 'icon-yincangmima' : 'icon-xianshimima'"
|
||||
@click="isShowPassword = !isShowPassword"
|
||||
>
|
||||
</i>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
@ -69,6 +76,7 @@ export default defineComponent({
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const state = reactive({
|
||||
isShowPassword: false,
|
||||
ruleForm: {
|
||||
userName: 'admin',
|
||||
password: '123456',
|
||||
@ -162,6 +170,14 @@ export default defineComponent({
|
||||
<style scoped lang="scss">
|
||||
.login-content-form {
|
||||
margin-top: 20px;
|
||||
.login-content-password {
|
||||
display: inline-block;
|
||||
width: 25px;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
color: #909399;
|
||||
}
|
||||
}
|
||||
.login-content-code {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
@ -4,7 +4,7 @@
|
||||
<el-input
|
||||
type="text"
|
||||
:placeholder="$t('message.mobile.placeholder1')"
|
||||
prefix-icon="el-icon-user"
|
||||
prefix-icon="iconfont icon-dianhua"
|
||||
v-model="ruleForm.userName"
|
||||
clearable
|
||||
autocomplete="off"
|
||||
@ -25,7 +25,7 @@
|
||||
></el-input>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-button>{{ $t('message.mobile.codeText') }}</el-button>
|
||||
<el-button class="login-content-code">{{ $t('message.mobile.codeText') }}</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
@ -58,6 +58,13 @@ export default defineComponent({
|
||||
<style scoped lang="scss">
|
||||
.login-content-form {
|
||||
margin-top: 20px;
|
||||
::v-deep(.el-input__icon) {
|
||||
display: inline-block;
|
||||
}
|
||||
.login-content-code {
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
}
|
||||
.login-content-submit {
|
||||
width: 100%;
|
||||
letter-spacing: 2px;
|
||||
|
@ -8,7 +8,6 @@
|
||||
:props="{ expandTrigger: 'hover', value: 'code', label: 'name' }"
|
||||
size="small"
|
||||
clearable
|
||||
class="w100"
|
||||
>
|
||||
</el-cascader>
|
||||
</el-card>
|
||||
@ -43,9 +42,9 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { toRefs, reactive, onMounted } from 'vue';
|
||||
import { toRefs, reactive, onMounted, defineComponent } from 'vue';
|
||||
import threeLevelLinkageJson from '/@/mock/threeLevelLinkage.json';
|
||||
export default {
|
||||
export default defineComponent({
|
||||
name: 'pagesCityLinkage',
|
||||
setup() {
|
||||
const state = reactive({
|
||||
@ -93,5 +92,5 @@ export default {
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
54
src/views/pages/formI18n/index.vue
Normal file
54
src/views/pages/formI18n/index.vue
Normal file
@ -0,0 +1,54 @@
|
||||
<template>
|
||||
<div class="form-i18n-container">
|
||||
<el-card shadow="hover" header="表单国际化演示(不适用于动态项 form-item)">
|
||||
<div style="text-align: center; margin-top: 15px">
|
||||
<el-radio-group v-model="radio" size="small" @change="onRadioChange">
|
||||
<el-radio-button label="zh-cn">中文简体</el-radio-button>
|
||||
<el-radio-button label="en">英文</el-radio-button>
|
||||
<el-radio-button label="zh-tw">中文繁体</el-radio-button>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<el-form :model="form" size="small" label-width="100px" class="mt35 mb35">
|
||||
<el-row :gutter="35">
|
||||
<el-col :xs="24" :sm="12" :md="8" :lg="8" :xl="8" class="mb20">
|
||||
<el-form-item :label="$t('message.formI18nLabel.name')">
|
||||
<el-input v-model="form.name" :placeholder="$t('message.formI18nPlaceholder.name')" clearable></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8" :lg="8" :xl="8" class="mb20">
|
||||
<el-form-item :label="$t('message.formI18nLabel.email')">
|
||||
<el-input v-model="form.email" :placeholder="$t('message.formI18nPlaceholder.email')" clearable></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8" :lg="8" :xl="8" class="mb20">
|
||||
<el-form-item :label="$t('message.formI18nLabel.autograph')">
|
||||
<el-input v-model="form.autograph" :placeholder="$t('message.formI18nPlaceholder.autograph')" clearable></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { toRefs, reactive, defineComponent, getCurrentInstance } from 'vue';
|
||||
export default defineComponent({
|
||||
name: 'pagesFormI18n',
|
||||
setup() {
|
||||
const { proxy } = getCurrentInstance() as any;
|
||||
const state = reactive({
|
||||
radio: 'zh-cn',
|
||||
form: {},
|
||||
});
|
||||
// 单选框改变时
|
||||
const onRadioChange = () => {
|
||||
proxy.$i18n.locale = state.radio;
|
||||
};
|
||||
return {
|
||||
onRadioChange,
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
Loading…
Reference in New Issue
Block a user