update 组件

master
管理员 8 months ago
parent 2fffc12f5c
commit 423087ff59

@ -165,54 +165,24 @@ body {
} }
&>.h2 { &>.h2 {
margin-top: 0.6em; margin-top: 0.7em;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
color: var(--primary-color);
& label:has(input[type="checkbox"]) { * {
margin-top: .3em; font-size: .8rem;
font-size: .9em;
--color: #aaa;
color: var(--color);
display: flex;
justify-content: flex-start;
align-items: center;
cursor: pointer;
font-weight: normal;
&::before {
content: "";
background-color: var(--color);
border: .13em solid var(--color);
box-sizing: border-box;
padding: .17em;
background-clip: content-box;
height: 1em;
width: 1em;
margin-right: .3em;
border-radius: 2em;
}
&>input[type="checkbox"] {
display: none;
}
} }
& label:has(input[type="checkbox"]:checked) { &>div>div, a {
--color: var(--primary-color);
}
& label:hover {
filter: brightness(0.8);
}
& a {
color: var(--primary-color);
text-decoration: none; text-decoration: none;
&:hover { &:hover {
filter: brightness(0.7); filter: brightness(1.1);
}
&:active {
filter: brightness(.9);
} }
} }
} }

@ -0,0 +1,228 @@
<template>
<div class="w-code">
<w-icon icon-class="clipboard" @click="copy" />
<pre><code ref="codeRef" :class="props.language?['language-'+props.language]:[]"><slot></slot></code></pre>
</div>
</template>
<script setup>
import hljs from 'highlight.js';
import 'highlight.js/styles/github.css';
import { ElMessage } from 'element-plus'
import { onMounted } from 'vue';
const props = defineProps({
language: {
type: String,
default: ''
}
})
const codeRef = ref(null);
const copy = () => {
navigator.clipboard.writeText(codeRef.value.textContent).then(() => {
ElMessage.success('复制成功');
})
}
onMounted(() => {
hljs.highlightElement(codeRef.value);
})
const getCode = () => {
return codeRef.value.textContent;
}
const setCode = (code) => {
if(props.language){
codeRef.value.innerHTML = hljs.highlight(code, { language: props.language }).value;
}else{
codeRef.value.innerHTML = hljs.highlightAuto(code).value;
}
}
defineExpose({
copy,
getCode,
setCode,
})
</script>
<style lang="scss">
.w-code {
background-color: #0001;
margin: 1em;
padding: 0em;
border: solid 1px #0002;
border-radius: .5em;
position: relative;
&>:first-child {
position: absolute;
right: .5em;
top: .5em;
cursor: pointer;
opacity: 0;
transition: all .3s;
}
&:hover>:first-child {
opacity: 0.7;
&:hover {
opacity: 1;
}
&:active {
opacity: .85;
}
}
.hljs {
background: #0000 !important;
}
}
.dark {
pre code.hljs {
display: block;
overflow-x: auto;
padding: 1em
}
code.hljs {
padding: 3px 5px
}
/*!
Theme: GitHub Dark
Description: Dark theme as seen on github.com
Author: github.com
Maintainer: @Hirse
Updated: 2021-05-15
Outdated base version: https://github.com/primer/github-syntax-dark
Current colors taken from GitHub's CSS
*/
.hljs {
color: #c9d1d9;
background: #0d1117
}
.hljs-doctag,
.hljs-keyword,
.hljs-meta .hljs-keyword,
.hljs-template-tag,
.hljs-template-variable,
.hljs-type,
.hljs-variable.language_ {
/* prettylights-syntax-keyword */
color: #ff7b72
}
.hljs-title,
.hljs-title.class_,
.hljs-title.class_.inherited__,
.hljs-title.function_ {
/* prettylights-syntax-entity */
color: #d2a8ff
}
.hljs-attr,
.hljs-attribute,
.hljs-literal,
.hljs-meta,
.hljs-number,
.hljs-operator,
.hljs-variable,
.hljs-selector-attr,
.hljs-selector-class,
.hljs-selector-id {
/* prettylights-syntax-constant */
color: #79c0ff
}
.hljs-regexp,
.hljs-string,
.hljs-meta .hljs-string {
/* prettylights-syntax-string */
color: #a5d6ff
}
.hljs-built_in,
.hljs-symbol {
/* prettylights-syntax-variable */
color: #ffa657
}
.hljs-comment,
.hljs-code,
.hljs-formula {
/* prettylights-syntax-comment */
color: #8b949e
}
.hljs-name,
.hljs-quote,
.hljs-selector-tag,
.hljs-selector-pseudo {
/* prettylights-syntax-entity-tag */
color: #7ee787
}
.hljs-subst {
/* prettylights-syntax-storage-modifier-import */
color: #c9d1d9
}
.hljs-section {
/* prettylights-syntax-markup-heading */
color: #1f6feb;
font-weight: bold
}
.hljs-bullet {
/* prettylights-syntax-markup-list */
color: #f2cc60
}
.hljs-emphasis {
/* prettylights-syntax-markup-italic */
color: #c9d1d9;
font-style: italic
}
.hljs-strong {
/* prettylights-syntax-markup-bold */
color: #c9d1d9;
font-weight: bold
}
.hljs-addition {
/* prettylights-syntax-markup-inserted */
color: #aff5b4;
background-color: #033a16
}
.hljs-deletion {
/* prettylights-syntax-markup-deleted */
color: #ffdcd7;
background-color: #67060c
}
.hljs-char.escape_,
.hljs-link,
.hljs-params,
.hljs-property,
.hljs-punctuation,
.hljs-tag {
/* purposely ignored */
}
}
</style>

@ -59,6 +59,10 @@ const props = defineProps({
return r.data return r.data
} }
}, },
before: {
type: Function,
default: (file) => { return true }
},
/** /**
* 上传路径前缀 * 上传路径前缀
*/ */
@ -256,6 +260,9 @@ const fileInputChange = () => {
} }
const addUploadFile = async (file) => { const addUploadFile = async (file) => {
if (!props.before(file)) {
return
}
if (props.max > 1 && props.max == data.value.length) { if (props.max > 1 && props.max == data.value.length) {
ElMessage.error('最多只允许上传' + props.max + '个文件') ElMessage.error('最多只允许上传' + props.max + '个文件')
return return
@ -469,7 +476,7 @@ const chunkFile = (file, chunksize) => {
return chunksList; return chunksList;
} }
defineExpose({ open, reloadUploadKey }) defineExpose({ open, reloadUploadKey,addUploadFile })
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.doing { .doing {

@ -0,0 +1,53 @@
<template>
<svg :class="svgClass" aria-hidden="true">
<use :xlink:href="iconName" :fill="color" />
</svg>
</template>
<script>
export default defineComponent({
props: {
iconClass: {
type: String,
required: true
},
className: {
type: String,
default: ''
},
color: {
type: String,
default: ''
},
},
setup(props) {
return {
iconName: computed(() => `#icon-${props.iconClass}`),
svgClass: computed(() => {
if (props.className) {
return `svg-icon ${props.className}`
}
return 'svg-icon'
})
}
}
})
</script>
<style scope lang="scss">
.sub-el-icon,
.nav-icon {
display: inline-block;
font-size: 15px;
margin-right: 12px;
position: relative;
}
.svg-icon {
width: 1em;
height: 1em;
position: relative;
fill: currentColor;
vertical-align: -2px;
}
</style>

@ -99,6 +99,10 @@ const props = defineProps({
return r.data return r.data
} }
}, },
before: {
type: Function,
default: (file) => { return true }
},
/** /**
* 上传路径前缀 * 上传路径前缀
*/ */
@ -289,7 +293,10 @@ const fileInputChange = () => {
} }
const addUploadFile = async (file) => { const addUploadFile = async (file) => {
console.debug(file)
if (!props.before(file)) {
return
}
if (props.max > 1 && props.max == data.value.length) { if (props.max > 1 && props.max == data.value.length) {
ElMessage.error('最多只允许上传' + props.max + '个文件') ElMessage.error('最多只允许上传' + props.max + '个文件')
return return
@ -337,7 +344,7 @@ const uploadFiles = async () => {
console.debug('end') console.debug('end')
}).finally(() => { }).finally(() => {
data.value = data.value.filter(a => !a.error && !a.abort) data.value = data.value.filter(a => !a.error && !a.abort)
console.debug('finally',data.value) console.debug('finally', data.value)
doing.value = false doing.value = false
uploading.value = false uploading.value = false
}) })
@ -412,7 +419,7 @@ const uploadFile = async (index, retry = 0) => {
} }
defineExpose({ open, reloadUploadKey }) defineExpose({ open, reloadUploadKey, addUploadFile })
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.doing { .doing {

@ -1,5 +1,5 @@
<template> <template>
<el-image-viewer v-if="imgShow" @close="imgShow=false" ref="imgRef" :url-list="[img]" /> <el-image-viewer v-if="imgShow" @close="imgShow=false" ref="imgRef" :url-list="img" />
</template> </template>
<script setup> <script setup>
@ -7,13 +7,18 @@ import { ref, getCurrentInstance } from 'vue'
const { proxy } = getCurrentInstance(); const { proxy } = getCurrentInstance();
const img = ref(""); const img = ref([]);
const imgShow = ref(false); const imgShow = ref(false);
const open = async (src) => { const open = async (src) => {
img.value = src; if(Array.isArray(src)){
img.value = src;
}else{
img.value = [src];
}
imgShow.value = true imgShow.value = true
await proxy.$nextTick(); await proxy.$nextTick();
} }

@ -0,0 +1,77 @@
<template>
<div class="w-tags-input">
<el-tag v-for="(tag, index) in model" :key="index" closable :disable-transitions="false" :type="props.type"
@close="handleClose(index)">
{{ index }} : {{ tag }}
</el-tag>
<el-input v-if="inputVisible" ref="inputRef" v-model="inputValue" :style="{ width: props.placeholder.length * 2 + 1 + 'em' }"
size="small" placeholder="key : value" @keyup.enter="handleInputConfirm" @blur="handleInputConfirm" />
<el-button v-else class="button-new-tag" size="small" @click="showInput">
{{ props.placeholder }}
</el-button>
</div>
</template>
<script setup>
import { ElMessage } from 'element-plus';
import { nextTick, ref } from 'vue'
const model = defineModel({
type: Object,
required: true
});
const props = defineProps({
/**
* 输入提示
*/
placeholder: {
type: String,
default: "新增配置项",
},
type: {
type: String,
default: 'primary'
}
});
const inputValue = ref('')
const inputVisible = ref(false);
const inputRef = ref(undefined);
const handleClose = (index) => {
delete model.value[index];
};
const showInput = () => {
inputVisible.value = true
nextTick(() => {
inputRef.value?.input?.focus();
})
}
const handleInputConfirm = () => {
if (inputValue.value) {
if (inputValue.value.indexOf(":")>0) {
model.value[inputValue.value.split(':')[0].trim()] = inputValue.value.split(':')[1].trim();
} else {
ElMessage.error('输入格式错误');
}
}
inputVisible.value = false
inputValue.value = ''
}
</script>
<style lang="scss" scoped>
.w-tags-input {
display: flex;
flex-wrap: wrap;
&>* {
margin: 0 1em 1em 0;
}
}
</style>

@ -27,8 +27,8 @@
<img :src="codeUrl" @click="getCode" /> <img :src="codeUrl" @click="getCode" />
</div> </div>
<div class="h2"> <div class="h2">
<div><label><input type="checkbox" v-model="loginForm.rememberMe" />记住我</label></div> <div><div :class="{selected:loginForm.rememberMe}" @click="loginForm.rememberMe=!loginForm.rememberMe;" class="w-checkbox">记住密码</div></div>
<div v-if="false"><a href="javascript:void(0);" @click="ElMessageBox.alert('请联系管理员');">?</a></div> <div ><a href="javascript:void(0);" @click="ElMessageBox.alert('请联系管理员');">?</a></div>
</div> </div>
<el-button :loading="loading" class="btn" size="large" type="primary" @click.prevent="handleLogin"> <el-button :loading="loading" class="btn" size="large" type="primary" @click.prevent="handleLogin">
<span v-if="!loading"> </span> <span v-if="!loading"> </span>

@ -15,17 +15,18 @@
</div> </div>
</template> </template>
<script setup> <script setup>
import { ref } from "vue";
const list = ref([]); const list = ref([]);
let files = import.meta.glob("@/views/test/*.vue"); let files = import.meta.glob("./test/*.vue");
for (let fileName in files) { for (let fileName in files) {
let moduleName = fileName.replace(/^.*\/(\w+)\.vue$/, "$1"); let moduleName = fileName.replace(/^.*\/(\w+)\.vue$/, "$1");
// if (moduleName == "index") { if (moduleName == "index") {
// continue; continue;
// } }
list.value.push(moduleName); list.value.push(moduleName);
} }
list.value.sort((a, b) => a.localeCompare(b));
list.value.unshift("index");
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.w-test { .w-test {

@ -0,0 +1,51 @@
<template>
<div style="font-size: .7rem;">
<h1>图标</h1>
<w-code language="html">{{ `<w-icon icon-class="404" />
<w-icon icon-class="404" class-name="icon-test" color="var(--el-color-error)" style="font-size: 10em; color: var(--el-color-primary);" />
.icon-test {
color: var(--el-color-success);
font-size: 5em;
}
` }}</w-code>
<w-icon icon-class="404" />
<w-icon icon-class="404" class-name="icon-test" color="var(--el-color-error)" style="font-size: 10em; color: var(--el-color-primary);" />
<h2>使用说明</h2>
<ol style="margin: 1em 2em;">
<li>icon-class: 必填图片类别自定义的图片请放入/src/assets/icons/目录下</li>
<li>color: 图标颜色,优先级高本质定义svg的fill属性</li>
<li>class-name: 使用的css类名可以定义颜色和字体大小</li>
<li>style: 可以定义定义颜色和字体大小</li>
</ol>
<div class="w-flex icons">
<div v-for="item in icons" :key="item" class="w-flex-column">
<w-icon :icon-class="item" />
{{ item }}
</div>
</div>
</div>
</template>
<script setup>
import icons from "@/components/IconSelect/requireIcons";
</script>
<style lang="scss" scoped>
.icon-test {
color: var(--el-color-success);
font-size: 5em;
}
.icons {
flex-wrap: wrap;
justify-content: flex-start;
padding: 2em;
& > div {
padding: 2em;
svg {
width: 5em;
height: 5em;
margin-bottom: 0.5em;
color: var(--w-main);
}
}
}
</style>

@ -0,0 +1,9 @@
<template>
<div></div>
</template>
<script setup>
</script>
<style lang="scss" scoped>
</style>

@ -38,6 +38,7 @@ const getUploadKey =async () => {
<li>属性watermark是否添加水印默认true </li> <li>属性watermark是否添加水印默认true </li>
<li>属性noEffect是否无效果本质设置css属性默认false </li> <li>属性noEffect是否无效果本质设置css属性默认false </li>
<li>属性list是否显示列表默认true</li> <li>属性list是否显示列表默认true</li>
<li>属性before文件添加之前的方法返回true则继续</li>
<li>css属性--image-size图片显示大小默认 10em </li> <li>css属性--image-size图片显示大小默认 10em </li>
<li>css属性--image-border-radius图片显示圆角默认 .4em</li> <li>css属性--image-border-radius图片显示圆角默认 .4em</li>
<li>css属性--image-margin图片外边距默认 .5em .5em 0 0</li> <li>css属性--image-margin图片外边距默认 .5em .5em 0 0</li>
@ -116,6 +117,7 @@ const getUploadKey =async () => {
<li>属性chunksize分片大小默认5Mb不建议修改</li> <li>属性chunksize分片大小默认5Mb不建议修改</li>
<li>属性list是否显示列表默认true</li> <li>属性list是否显示列表默认true</li>
<li>属性border文件项是否显示边框默认true</li> <li>属性border文件项是否显示边框默认true</li>
<li>属性before文件添加之前的方法返回true则继续</li>
<li>插槽button上传按钮插槽</li> <li>插槽button上传按钮插槽</li>
<li>插槽default文件列表作用域list不建议定义</li> <li>插槽default文件列表作用域list不建议定义</li>
<li>事件changemodelValue发送了变化</li> <li>事件changemodelValue发送了变化</li>

Loading…
Cancel
Save