01431511 by renchao@pashanhoo.com

Merge branch 'dev'

2 parents 0f62fe97 5b753536
1 <!-- 1 <!--
2 * @Description: 2 * @Description:
3 * @Autor: renchao 3 * @Autor: renchao
4 * @LastEditTime: 2023-07-20 10:22:20 4 * @LastEditTime: 2023-07-25 16:06:03
5 --> 5 -->
6 <template> 6 <template>
7 <label class="el-checkbox" :class="[ 7 <label class="el-checkbox" :class="[
...@@ -46,9 +46,7 @@ ...@@ -46,9 +46,7 @@
46 default: '' 46 default: ''
47 } 47 }
48 }, 48 },
49
50 componentName: 'ElCheckbox', 49 componentName: 'ElCheckbox',
51
52 data () { 50 data () {
53 return { 51 return {
54 selfModel: false, 52 selfModel: false,
...@@ -56,7 +54,6 @@ ...@@ -56,7 +54,6 @@
56 isLimitExceeded: false 54 isLimitExceeded: false
57 }; 55 };
58 }, 56 },
59
60 computed: { 57 computed: {
61 model: { 58 model: {
62 /** 59 /**
...@@ -129,7 +126,6 @@ ...@@ -129,7 +126,6 @@
129 store () { 126 store () {
130 return this._checkboxGroup ? this._checkboxGroup.value : this.value; 127 return this._checkboxGroup ? this._checkboxGroup.value : this.value;
131 }, 128 },
132
133 /** 129 /**
134 * @description: isLimitDisabled 130 * @description: isLimitDisabled
135 * @author: renchao 131 * @author: renchao
......
1 <!--
2 * @Description:
3 * @Autor: renchao
4 * @LastEditTime: 2023-07-25 16:10:17
5 -->
1 <template> 6 <template>
2 <transition name="el-loading-fade" @after-leave="handleAfterLeave"> 7 <transition name="el-loading-fade" @after-leave="handleAfterLeave">
3 <div v-show="visible" class="el-loading-mask" :style="{ backgroundColor: background || '' }" 8 <div v-show="visible" class="el-loading-mask" :style="{ backgroundColor: background || '' }"
...@@ -9,37 +14,35 @@ ...@@ -9,37 +14,35 @@
9 </div> 14 </div>
10 </transition> 15 </transition>
11 </template> 16 </template>
12
13 <script> 17 <script>
14 export default { 18 export default {
15 data () { 19 data () {
16 return { 20 return {
17 text: null, 21 text: null,
18 spinner: null, 22 spinner: null,
19 background: null, 23 background: null,
20 fullscreen: true, 24 fullscreen: true,
21 visible: false, 25 visible: false,
22 customClass: '' 26 customClass: ''
23 }; 27 };
24 },
25
26 methods: {
27 handleAfterLeave () {
28 this.$emit('after-leave');
29 }, 28 },
30 setText (text) { 29 methods: {
31 this.text = text; 30 handleAfterLeave () {
31 this.$emit('after-leave');
32 },
33 setText (text) {
34 this.text = text;
35 }
32 } 36 }
33 } 37 };
34 };
35 </script> 38 </script>
36 <style scoped lang="scss"> 39 <style scoped lang="scss">
37 .el-loading-spinner { 40 .el-loading-spinner {
38 margin-top: -100px !important; 41 margin-top: -100px !important;
39 42
40 .img { 43 .img {
41 width: 80px; 44 width: 80px;
42 height: 80px; 45 height: 80px;
46 }
43 } 47 }
44 }
45 </style> 48 </style>
...\ No newline at end of file ...\ No newline at end of file
......
1 <!--
2 * @Description:
3 * @Autor: renchao
4 * @LastEditTime: 2023-07-25 16:10:08
5 -->
1 <template> 6 <template>
2 <transition name="fade"> 7 <transition name="fade">
3 <!--主要内容--> 8 <!--主要内容-->
...@@ -18,163 +23,163 @@ ...@@ -18,163 +23,163 @@
18 </transition> 23 </transition>
19 </template> 24 </template>
20 <script> 25 <script>
21 export default { 26 export default {
22 props: { 27 props: {
23 noticeList: { 28 noticeList: {
24 type: Array, 29 type: Array,
25 default: [] 30 default: []
26 } 31 }
27 },
28 data () {
29 return {
30 speed: 50, // 速度(单位px/s)
31 backWidth: '', // 父级宽度
32 backHeight: '', // 父级高度
33 wordLength: '', // 文本长度
34 state: 1,
35 firstAnimationTime: '', // 状态一动画效果
36 secondAnimationTime: '', // 状态二动画效果
37 };
38 },
39 watch: {
40 noticeList: {
41 handler (newName, oldName) {
42 let that = this
43 this.Listener();
44 setTimeout(res => {
45 that.getData();
46 }, 100);
47 },
48 deep: true
49 }
50 },
51 methods: {
52 /**
53 * @description: handleNotice
54 * @param {*} item
55 * @author: renchao
56 */
57 handleNotice (item) {
58 this.$alertMes(item.noticeTitle, item.noticeContent)
59 },
60 /**
61 * @description: 获取数据
62 * @author: renchao
63 */
64 getData () {
65 let style = document.styleSheets[0];
66 let text = this.$refs.text;
67 let back = this.$refs.back;
68 this.backWidth = back.offsetWidth;
69 this.backHeight = back.offsetHeight;
70 text.style.lineHeight = this.backHeight + 'px';
71 this.wordLength = text.offsetWidth;
72 this.ComputationTime(); // 计算时间
73 style.insertRule(
74 `@keyframes firstAnimation {0% {left:0px;}100% {left:-${this.wordLength}px;}}`
75 );
76 style.insertRule(
77 `@keyframes secondAnimation {0% {left:${this.backWidth}px;}100% {left:-${this.wordLength}px;}}`
78 );
79 setTimeout(res => {
80 this.changeState();
81 }, 300);
82 }, 32 },
83 /** 33 data () {
84 * @description: 用速度计算时间(想要保持速度一样,2种状态时间不同需算出) 34 return {
85 * @author: renchao 35 speed: 50, // 速度(单位px/s)
86 */ 36 backWidth: '', // 父级宽度
87 ComputationTime () { 37 backHeight: '', // 父级高度
88 this.firstAnimationTime = this.wordLength / this.speed; 38 wordLength: '', // 文本长度
89 this.secondAnimationTime = 39 state: 1,
90 (this.wordLength + this.backWidth) / this.speed; 40 firstAnimationTime: '', // 状态一动画效果
41 secondAnimationTime: '', // 状态二动画效果
42 };
91 }, 43 },
92 /** 44 watch: {
93 * @description: 根据状态切换动画 45 noticeList: {
94 * @author: renchao 46 handler (newName, oldName) {
95 */ 47 let that = this
96 changeState () { 48 this.Listener();
97 let text = this.$refs.text; 49 setTimeout(res => {
98 if (this.state == 1) { 50 that.getData();
99 text.style.animation = `firstAnimation ${this.firstAnimationTime}s linear`; 51 }, 100);
100 this.state = 2; 52 },
101 } else { 53 deep: true
102 text.style.animation = `secondAnimation ${this.secondAnimationTime}s linear infinite`;
103 } 54 }
104 }, 55 },
105 /** 56 methods: {
106 * @description: Listener 57 /**
107 * @author: renchao 58 * @description: handleNotice
108 */ 59 * @param {*} item
109 Listener () { 60 * @author: renchao
110 let text = this.$refs.text; 61 */
111 text.addEventListener( 62 handleNotice (item) {
112 'animationend', 63 this.$alertMes(item.noticeTitle, item.noticeContent)
113 res => { 64 },
65 /**
66 * @description: 获取数据
67 * @author: renchao
68 */
69 getData () {
70 let style = document.styleSheets[0];
71 let text = this.$refs.text;
72 let back = this.$refs.back;
73 this.backWidth = back.offsetWidth;
74 this.backHeight = back.offsetHeight;
75 text.style.lineHeight = this.backHeight + 'px';
76 this.wordLength = text.offsetWidth;
77 this.ComputationTime(); // 计算时间
78 style.insertRule(
79 `@keyframes firstAnimation {0% {left:0px;}100% {left:-${this.wordLength}px;}}`
80 );
81 style.insertRule(
82 `@keyframes secondAnimation {0% {left:${this.backWidth}px;}100% {left:-${this.wordLength}px;}}`
83 );
84 setTimeout(res => {
114 this.changeState(); 85 this.changeState();
115 }, 86 }, 300);
116 false 87 },
117 ) 88 /**
118 }, 89 * @description: 用速度计算时间(想要保持速度一样,2种状态时间不同需算出)
119 /** 90 * @author: renchao
120 * @description: mouseOver 91 */
121 * @author: renchao 92 ComputationTime () {
122 */ 93 this.firstAnimationTime = this.wordLength / this.speed;
123 mouseOver () { 94 this.secondAnimationTime =
124 let text = this.$refs.text; 95 (this.wordLength + this.backWidth) / this.speed;
125 text.style.animationPlayState = 'paused' 96 },
126 }, 97 /**
127 /** 98 * @description: 根据状态切换动画
128 * @description: mouseLeave 99 * @author: renchao
129 * @author: renchao 100 */
130 */ 101 changeState () {
131 mouseLeave () { 102 let text = this.$refs.text;
132 let text = this.$refs.text; 103 if (this.state == 1) {
133 text.style.animationPlayState = '' 104 text.style.animation = `firstAnimation ${this.firstAnimationTime}s linear`;
105 this.state = 2;
106 } else {
107 text.style.animation = `secondAnimation ${this.secondAnimationTime}s linear infinite`;
108 }
109 },
110 /**
111 * @description: Listener
112 * @author: renchao
113 */
114 Listener () {
115 let text = this.$refs.text;
116 text.addEventListener(
117 'animationend',
118 res => {
119 this.changeState();
120 },
121 false
122 )
123 },
124 /**
125 * @description: mouseOver
126 * @author: renchao
127 */
128 mouseOver () {
129 let text = this.$refs.text;
130 text.style.animationPlayState = 'paused'
131 },
132 /**
133 * @description: mouseLeave
134 * @author: renchao
135 */
136 mouseLeave () {
137 let text = this.$refs.text;
138 text.style.animationPlayState = ''
139 }
134 } 140 }
135 } 141 };
136 };
137 </script> 142 </script>
138 <style lang="scss" scoped> 143 <style lang="scss" scoped>
139 .noticebar { 144 .noticebar {
140 display: flex; 145 display: flex;
141 align-items: center; 146 align-items: center;
142 width: 100%; 147 width: 100%;
143 height: 28px; 148 height: 28px;
144 background: rgba(0, 0, 0, 0.1); 149 background: rgba(0, 0, 0, 0.1);
145 150
146 .icon { 151 .icon {
147 img { 152 img {
148 height: 100%; 153 height: 100%;
149 width: 100%; 154 width: 100%;
155 }
150 } 156 }
151 }
152
153 .back {
154 overflow: hidden;
155 white-space: nowrap;
156 margin: 0 auto;
157 height: 100%;
158 width: 100%;
159 cursor: pointer;
160 position: relative;
161 font-size: 14px;
162 color: #fff;
163 157
164 .text { 158 .back {
165 position: absolute; 159 overflow: hidden;
166 display: inline-block; 160 white-space: nowrap;
167 padding: 2px 0; 161 margin: 0 auto;
168 display: flex; 162 height: 100%;
163 width: 100%;
164 cursor: pointer;
165 position: relative;
166 font-size: 14px;
167 color: #fff;
169 168
170 p { 169 .text {
171 margin-right: 80px; 170 position: absolute;
171 display: inline-block;
172 padding: 2px 0;
172 display: flex; 173 display: flex;
173 align-items: center; 174
174 height: 28px; 175 p {
175 line-height: 28px; 176 margin-right: 80px;
177 display: flex;
178 align-items: center;
179 height: 28px;
180 line-height: 28px;
181 }
176 } 182 }
177 } 183 }
178 } 184 }
179 }
180 </style> 185 </style>
......
1 <!--
2 * @Description:
3 * @Autor: renchao
4 * @LastEditTime: 2023-07-25 16:09:59
5 -->
1 <template> 6 <template>
2 <div style="width: 100%;height: 100%"> 7 <div style="width: 100%;height: 100%">
3 <vue-photo-zoom-pro :width="bigWidth" :url="url" :type="type" :scale="scale" :out-show="showType" 8 <vue-photo-zoom-pro :width="bigWidth" :url="url" :type="type" :scale="scale" :out-show="showType"
...@@ -5,7 +10,6 @@ ...@@ -5,7 +10,6 @@
5 </vue-photo-zoom-pro> 10 </vue-photo-zoom-pro>
6 </div> 11 </div>
7 </template> 12 </template>
8
9 <script> 13 <script>
10 import vuePhotoZoomPro from '@/components/PhotoZoom/vue-photo-zoom-pro' 14 import vuePhotoZoomPro from '@/components/PhotoZoom/vue-photo-zoom-pro'
11 export default { 15 export default {
......
1 <!--
2 * @Description:
3 * @Autor: renchao
4 * @LastEditTime: 2023-07-25 16:06:21
5 -->
1 <template> 6 <template>
2 <transition name="msgbox-fade" v-if="myShow"> 7 <transition name="msgbox-fade" v-if="myShow">
3 <div class="ls-mask" v-loading="loading"> 8 <div class="ls-mask" v-loading="loading">
...@@ -21,181 +26,179 @@ ...@@ -21,181 +26,179 @@
21 </transition> 26 </transition>
22 </template> 27 </template>
23 <script> 28 <script>
24 export default { 29 export default {
25 name: 'index', 30 name: 'index',
26 data () { 31 data () {
27 return { 32 return {
28 title: '标题', 33 title: '标题',
29 editItem: "", 34 editItem: "",
30 formData: undefined,//父组件传递的参数 负责传给子组件 35 formData: undefined,//父组件传递的参数 负责传给子组件
31 btnShow: false, 36 btnShow: false,
32 cancel: function () { }, 37 cancel: function () { },
33 confirm: function () { }, 38 confirm: function () { },
34 cancelText: '取消', 39 cancelText: '取消',
35 confirmText: '确认', 40 confirmText: '确认',
36 isSync: false, 41 isSync: false,
37 isShow: false, 42 isShow: false,
38 myShow: false, 43 myShow: false,
39 titleStyle: 'center', 44 titleStyle: 'center',
40 width: "75%", 45 width: "75%",
41 height: "auto", 46 height: "auto",
42 contentHeight: "", 47 contentHeight: "",
43 iconClass: "", 48 iconClass: "",
44 key: 0 49 key: 0
45 } 50 }
46 }, 51 },
47 props: { 52 props: {
48 loading: { type: Boolean, default: false }, 53 loading: { type: Boolean, default: false },
49 }, 54 },
50 watch: { 55 watch: {
51 isShow (newValue) { 56 isShow (newValue) {
52 this.editItem = this.loadViewFn(this.editItem) 57 this.editItem = this.loadViewFn(this.editItem)
53 document.body.appendChild(this.$el); 58 document.body.appendChild(this.$el);
54 this.myShow = newValue 59 this.myShow = newValue
55 } 60 }
56 }, 61 },
57 mounted () { 62 mounted () {
58 /** 63 /**
59 * @description: 计算滚动条高度 64 * @description: 计算滚动条高度
60 * @author: renchao 65 * @author: renchao
61 */ 66 */
62 setTimeout(() => { 67 setTimeout(() => {
63 if (this.btnShow) { 68 if (this.btnShow) {
64 if (this.height == 'auto') { 69 if (this.height == 'auto') {
65 this.contentHeight = (this.$refs.contentRef.offsetHeight) + 'px' 70 this.contentHeight = (this.$refs.contentRef.offsetHeight) + 'px'
66 } else { 71 } else {
67 this.contentHeight = this.height 72 this.contentHeight = this.height
68 } 73 }
69 } else {
70 if (this.height == 'auto') {
71 this.contentHeight = (this.$refs.contentRef.offsetHeight) + 'px'
72 } else { 74 } else {
73 this.contentHeight = this.height 75 if (this.height == 'auto') {
76 this.contentHeight = (this.$refs.contentRef.offsetHeight) + 'px'
77 } else {
78 this.contentHeight = this.height
79 }
74 } 80 }
75 } 81 }, 300)
76 }, 300)
77 },
78 methods: {
79 /**
80 * @description: onCancel
81 * @author: renchao
82 */
83 onCancel () {
84 this.isShow = false
85 this.cancel()
86 }, 82 },
87 /** 83 methods: {
88 * @description: onConfirm 84 /**
89 * @author: renchao 85 * @description: onCancel
90 */ 86 * @author: renchao
91 onConfirm () { 87 */
92 this.loading = true 88 onCancel () {
93 let res = new Promise((resolve, reject) => {
94 this.confirm()
95 resolve(true)
96 })
97 if (res) {
98 this.isShow = false 89 this.isShow = false
90 this.cancel()
91 },
92 /**
93 * @description: onConfirm
94 * @author: renchao
95 */
96 onConfirm () {
97 this.loading = true
98 let res = new Promise((resolve, reject) => {
99 this.confirm()
100 resolve(true)
101 })
102 if (res) {
103 this.isShow = false
104 }
105 },
106 /**
107 * @description: loadingFn
108 * @param {*} e
109 * @author: renchao
110 */
111 loadingFn (e) { //加载状态
112 this.loading = e
113 },
114 /**
115 * @description: loadViewFn
116 * @param {*} view
117 * @author: renchao
118 */
119 loadViewFn (view) {
120 return (r) =>
121 require.ensure([], () =>
122 r(require(`@/views/${view}.vue`))
123 )
99 } 124 }
100 }, 125 },
101 /** 126 destroyed () {
102 * @description: loadingFn 127 if (this.appendToBody && this.$el && this.$el.parentNode) {
103 * @param {*} e 128 this.$el.parentNode.removeChild(this.$el);
104 * @author: renchao 129 }
105 */
106 loadingFn (e) { //加载状态
107 this.loading = e
108 },
109 /**
110 * @description: loadViewFn
111 * @param {*} view
112 * @author: renchao
113 */
114 loadViewFn (view) {
115 return (r) =>
116 require.ensure([], () =>
117 r(require(`@/views/${view}.vue`))
118 )
119 }
120 },
121 destroyed () {
122 if (this.appendToBody && this.$el && this.$el.parentNode) {
123 this.$el.parentNode.removeChild(this.$el);
124 } 130 }
125 } 131 }
126 }
127 </script> 132 </script>
128 <style scoped lang="scss" > 133 <style scoped lang="scss" >
129 .ls-mask { 134 .ls-mask {
130 width: 100%; 135 width: 100%;
131 height: 100%; 136 height: 100%;
132 z-index: 2000; 137 z-index: 2000;
133 position: fixed; 138 position: fixed;
134 left: 0; 139 left: 0;
135 top: 0; 140 top: 0;
136 background: rgba(0, 0, 0, 0.3); 141 background: rgba(0, 0, 0, 0.3);
137 142 }
138 }
139
140 .ls-mask-window {
141 background: white;
142 position: relative;
143 left: 50%;
144 top: 50%;
145 min-height: 200px;
146 transform: translate(-50%, -50%);
147 border-radius: 5px;
148 overflow: hidden;
149 }
150 143
151 .ls-mask-window b { 144 .ls-mask-window {
152 padding-left: 5px; 145 background: white;
153 } 146 position: relative;
147 left: 50%;
148 top: 50%;
149 min-height: 200px;
150 transform: translate(-50%, -50%);
151 border-radius: 5px;
152 overflow: hidden;
153 }
154 154
155 .ls-title { 155 .ls-mask-window b {
156 padding: 16px; 156 padding-left: 5px;
157 color: #ffffff; 157 }
158 font-size: 16px;
159 background: linear-gradient(3deg, #409EFF, #a7cbee);
160 }
161 158
162 .ls-title .svg-icon { 159 .ls-title {
163 font-size: 18px; 160 padding: 16px;
164 } 161 color: #ffffff;
162 font-size: 16px;
163 background: linear-gradient(3deg, #409eff, #a7cbee);
164 }
165 165
166 .mask-content { 166 .ls-title .svg-icon {
167 padding: 20px; 167 font-size: 18px;
168 width: 100%; 168 }
169 min-height: 30%;
170 max-height: 90vh;
171 overflow-y: scroll;
172 }
173 169
174 .ls-mask-footer { 170 .mask-content {
175 height: 50px; 171 padding: 20px;
176 display: flex; 172 width: 100%;
177 justify-content: center; 173 min-height: 30%;
178 width: 100%; 174 max-height: 90vh;
179 position: absolute; 175 overflow-y: scroll;
180 border-top: 1px solid $borderColor; 176 }
181 bottom: 0;
182 background: #ffffff;
183 border-bottom-left-radius: 5px;
184 border-bottom-right-radius: 5px;
185 overflow: hidden;
186 }
187 177
178 .ls-mask-footer {
179 height: 50px;
180 display: flex;
181 justify-content: center;
182 width: 100%;
183 position: absolute;
184 border-top: 1px solid $borderColor;
185 bottom: 0;
186 background: #ffffff;
187 border-bottom-left-radius: 5px;
188 border-bottom-right-radius: 5px;
189 overflow: hidden;
190 }
188 191
189 /deep/.closeStyle { 192 /deep/.closeStyle {
190 position: absolute; 193 position: absolute;
191 top: 13px; 194 top: 13px;
192 right: 26px; 195 right: 26px;
193 font-size: 24px; 196 font-size: 24px;
194 cursor: pointer; 197 cursor: pointer;
195 color: #409EFF; 198 color: #409eff;
196 } 199 }
197 200
198 /deep/.el-loading-mask { 201 /deep/.el-loading-mask {
199 background: none; 202 background: none;
200 } 203 }
201 </style> 204 </style>
......
1 <!--
2 * @Description:
3 * @Autor: renchao
4 * @LastEditTime: 2023-07-25 16:08:30
5 -->
1 <template> 6 <template>
2 <transition name="msgbox-fade"> 7 <transition name="msgbox-fade">
3 <div class="ls-mask" v-if="myShow"> 8 <div class="ls-mask" v-if="myShow">
......
1 <!--
2 * @Description:
3 * @Autor: renchao
4 * @LastEditTime: 2023-07-25 16:08:55
5 -->
1 <!--显示svg文件图标--> 6 <!--显示svg文件图标-->
2 <template> 7 <template>
3 <div v-if="isExternal" :style="styleExternalIcon" class="svg-external-icon svg-icon" v-on="$listeners" /> 8 <div v-if="isExternal" :style="styleExternalIcon" class="svg-external-icon svg-icon" v-on="$listeners" />
...@@ -5,59 +10,58 @@ ...@@ -5,59 +10,58 @@
5 <use :xlink:href="iconName" /> 10 <use :xlink:href="iconName" />
6 </svg> 11 </svg>
7 </template> 12 </template>
8
9 <script> 13 <script>
10 // doc: https://panjiachen.github.io/vue-element-admin-site/feature/component/svg-icon.html#usage 14 // doc: https://panjiachen.github.io/vue-element-admin-site/feature/component/svg-icon.html#usage
11 import { isExternal } from '@/utils/validate' 15 import { isExternal } from '@/utils/validate'
12 16
13 export default { 17 export default {
14 name: 'SvgIcon', 18 name: 'SvgIcon',
15 props: { 19 props: {
16 iconClass: { 20 iconClass: {
17 type: String, 21 type: String,
18 required: true 22 required: true
19 }, 23 },
20 className: { 24 className: {
21 type: String, 25 type: String,
22 default: '' 26 default: ''
23 }
24 },
25 computed: {
26 isExternal() {
27 return isExternal(this.iconClass)
28 },
29 iconName() {
30 return `#icon-${this.iconClass}`
31 },
32 svgClass() {
33 if (this.className) {
34 return 'svg-icon ' + this.className
35 } else {
36 return 'svg-icon'
37 } 27 }
38 }, 28 },
39 styleExternalIcon() { 29 computed: {
40 return { 30 isExternal () {
41 mask: `url(${this.iconClass}) no-repeat 50% 50%`, 31 return isExternal(this.iconClass)
42 '-webkit-mask': `url(${this.iconClass}) no-repeat 50% 50%` 32 },
33 iconName () {
34 return `#icon-${this.iconClass}`
35 },
36 svgClass () {
37 if (this.className) {
38 return 'svg-icon ' + this.className
39 } else {
40 return 'svg-icon'
41 }
42 },
43 styleExternalIcon () {
44 return {
45 mask: `url(${this.iconClass}) no-repeat 50% 50%`,
46 '-webkit-mask': `url(${this.iconClass}) no-repeat 50% 50%`
47 }
43 } 48 }
44 } 49 }
45 } 50 }
46 }
47 </script> 51 </script>
48 52
49 <style scoped> 53 <style scoped>
50 .svg-icon { 54 .svg-icon {
51 width: 1em; 55 width: 1em;
52 height: 1em; 56 height: 1em;
53 vertical-align: -0.15em; 57 vertical-align: -0.15em;
54 fill: currentColor; 58 fill: currentColor;
55 overflow: hidden; 59 overflow: hidden;
56 } 60 }
57 61
58 .svg-external-icon { 62 .svg-external-icon {
59 background-color: currentColor; 63 background-color: currentColor;
60 mask-size: cover!important; 64 mask-size: cover !important;
61 display: inline-block; 65 display: inline-block;
62 } 66 }
63 </style> 67 </style>
......
1 <!--
2 * @Description:
3 * @Autor: renchao
4 * @LastEditTime: 2023-07-25 16:09:09
5 -->
1 <template> 6 <template>
2 <el-color-picker v-model="theme" 7 <el-color-picker v-model="theme"
3 :predefine="['#409EFF', '#1890ff', '#304156', '#212121', '#11a983', '#13c2c2', '#6959CD', '#f5222d',]" 8 :predefine="['#409EFF', '#1890ff', '#304156', '#212121', '#11a983', '#13c2c2', '#6959CD', '#f5222d',]"
...@@ -5,137 +10,154 @@ ...@@ -5,137 +10,154 @@
5 </template> 10 </template>
6 11
7 <script> 12 <script>
8 const version = require('element-ui/package.json').version // element-ui version from node_modules 13 const version = require('element-ui/package.json').version // element-ui version from node_modules
9 const ORIGINAL_THEME = '#409EFF' // default color 14 const ORIGINAL_THEME = '#409EFF' // default color
10 15
11 export default { 16 export default {
12 data () { 17 data () {
13 return { 18 return {
14 chalk: '', // content of theme-chalk css 19 chalk: '', // content of theme-chalk css
15 theme: '' 20 theme: ''
16 } 21 }
17 },
18 computed: {
19 defaultTheme () {
20 return this.$store.state.app.theme
21 }
22 },
23 watch: {
24 defaultTheme: {
25 handler: function (val, oldVal) {
26 this.theme = val
27 },
28 immediate: true
29 }, 22 },
30 async theme (val) { 23 computed: {
31 const oldVal = this.chalk ? this.theme : ORIGINAL_THEME 24 defaultTheme () {
32 if (typeof val !== 'string') return 25 return this.$store.state.app.theme
33 const themeCluster = this.getThemeCluster(val.replace('#', '')) 26 }
34 const originalCluster = this.getThemeCluster(oldVal.replace('#', '')) 27 },
35 console.log(themeCluster, originalCluster) 28 watch: {
36 29 defaultTheme: {
37 const $message = this.$message({ 30 handler: function (val, oldVal) {
38 message: ' Compiling the theme', 31 this.theme = val
39 customClass: 'theme-message', 32 },
40 type: 'success', 33 immediate: true
41 duration: 0, 34 },
42 iconClass: 'el-icon-loading' 35 async theme (val) {
43 }) 36 const oldVal = this.chalk ? this.theme : ORIGINAL_THEME
44 37 if (typeof val !== 'string') return
45 const getHandler = (variable, id) => { 38 const themeCluster = this.getThemeCluster(val.replace('#', ''))
46 return () => { 39 const originalCluster = this.getThemeCluster(oldVal.replace('#', ''))
47 const originalCluster = this.getThemeCluster(ORIGINAL_THEME.replace('#', '')) 40 console.log(themeCluster, originalCluster)
48 const newStyle = this.updateStyle(this[variable], originalCluster, themeCluster) 41
49 42 const $message = this.$message({
50 let styleTag = document.getElementById(id) 43 message: ' Compiling the theme',
51 if (!styleTag) { 44 customClass: 'theme-message',
52 styleTag = document.createElement('style') 45 type: 'success',
53 styleTag.setAttribute('id', id) 46 duration: 0,
54 document.head.appendChild(styleTag) 47 iconClass: 'el-icon-loading'
48 })
49
50 const getHandler = (variable, id) => {
51 return () => {
52 const originalCluster = this.getThemeCluster(ORIGINAL_THEME.replace('#', ''))
53 const newStyle = this.updateStyle(this[variable], originalCluster, themeCluster)
54
55 let styleTag = document.getElementById(id)
56 if (!styleTag) {
57 styleTag = document.createElement('style')
58 styleTag.setAttribute('id', id)
59 document.head.appendChild(styleTag)
60 }
61 styleTag.innerText = newStyle
55 } 62 }
56 styleTag.innerText = newStyle
57 } 63 }
58 }
59 64
60 if (!this.chalk) { 65 if (!this.chalk) {
61 const url = `https://unpkg.com/element-ui@${version}/lib/theme-chalk/index.css` 66 const url = `https://unpkg.com/element-ui@${version}/lib/theme-chalk/index.css`
62 await this.getCSSString(url, 'chalk') 67 await this.getCSSString(url, 'chalk')
63 } 68 }
64 69
65 const chalkHandler = getHandler('chalk', 'chalk-style') 70 const chalkHandler = getHandler('chalk', 'chalk-style')
66 71
67 chalkHandler() 72 chalkHandler()
68 73
69 const styles = [].slice.call(document.querySelectorAll('style')) 74 const styles = [].slice.call(document.querySelectorAll('style'))
70 .filter(style => { 75 .filter(style => {
71 const text = style.innerText 76 const text = style.innerText
72 return new RegExp(oldVal, 'i').test(text) && !/Chalk Variables/.test(text) 77 return new RegExp(oldVal, 'i').test(text) && !/Chalk Variables/.test(text)
78 })
79 styles.forEach(style => {
80 const { innerText } = style
81 if (typeof innerText !== 'string') return
82 style.innerText = this.updateStyle(innerText, originalCluster, themeCluster)
73 }) 83 })
74 styles.forEach(style => {
75 const { innerText } = style
76 if (typeof innerText !== 'string') return
77 style.innerText = this.updateStyle(innerText, originalCluster, themeCluster)
78 })
79 84
80 this.$emit('change', val) 85 this.$emit('change', val)
81 86
82 $message.close() 87 $message.close()
83 } 88 }
84 },
85
86 methods: {
87 /**
88 * @description: updateStyle
89 * @param {*} style
90 * @param {*} oldCluster
91 * @param {*} newCluster
92 * @author: renchao
93 */
94 updateStyle (style, oldCluster, newCluster) {
95 let newStyle = style
96 oldCluster.forEach((color, index) => {
97 newStyle = newStyle.replace(new RegExp(color, 'ig'), newCluster[index])
98 })
99 return newStyle
100 }, 89 },
101 90
102 /** 91 methods: {
103 * @description: getCSSString 92 /**
104 * @param {*} url 93 * @description: updateStyle
105 * @param {*} variable 94 * @param {*} style
106 * @author: renchao 95 * @param {*} oldCluster
107 */ 96 * @param {*} newCluster
108 getCSSString (url, variable) { 97 * @author: renchao
109 return new Promise(resolve => { 98 */
110 const xhr = new XMLHttpRequest() 99 updateStyle (style, oldCluster, newCluster) {
111 xhr.onreadystatechange = () => { 100 let newStyle = style
112 if (xhr.readyState === 4 && xhr.status === 200) { 101 oldCluster.forEach((color, index) => {
113 this[variable] = xhr.responseText.replace(/@font-face{[^}]+}/, '') 102 newStyle = newStyle.replace(new RegExp(color, 'ig'), newCluster[index])
114 resolve() 103 })
104 return newStyle
105 },
106
107 /**
108 * @description: getCSSString
109 * @param {*} url
110 * @param {*} variable
111 * @author: renchao
112 */
113 getCSSString (url, variable) {
114 return new Promise(resolve => {
115 const xhr = new XMLHttpRequest()
116 xhr.onreadystatechange = () => {
117 if (xhr.readyState === 4 && xhr.status === 200) {
118 this[variable] = xhr.responseText.replace(/@font-face{[^}]+}/, '')
119 resolve()
120 }
121 }
122 xhr.open('GET', url)
123 xhr.send()
124 })
125 },
126
127 /**
128 * @description: getThemeCluster
129 * @param {*} theme
130 * @author: renchao
131 */
132 getThemeCluster (theme) {
133 const tintColor = (color, tint) => {
134 let red = parseInt(color.slice(0, 2), 16)
135 let green = parseInt(color.slice(2, 4), 16)
136 let blue = parseInt(color.slice(4, 6), 16)
137
138 if (tint === 0) { // when primary color is in its rgb space
139 return [red, green, blue].join(',')
140 } else {
141 red += Math.round(tint * (255 - red))
142 green += Math.round(tint * (255 - green))
143 blue += Math.round(tint * (255 - blue))
144
145 red = red.toString(16)
146 green = green.toString(16)
147 blue = blue.toString(16)
148
149 return `#${red}${green}${blue}`
115 } 150 }
116 } 151 }
117 xhr.open('GET', url)
118 xhr.send()
119 })
120 },
121 152
122 /** 153 const shadeColor = (color, shade) => {
123 * @description: getThemeCluster 154 let red = parseInt(color.slice(0, 2), 16)
124 * @param {*} theme 155 let green = parseInt(color.slice(2, 4), 16)
125 * @author: renchao 156 let blue = parseInt(color.slice(4, 6), 16)
126 */ 157
127 getThemeCluster (theme) { 158 red = Math.round((1 - shade) * red)
128 const tintColor = (color, tint) => { 159 green = Math.round((1 - shade) * green)
129 let red = parseInt(color.slice(0, 2), 16) 160 blue = Math.round((1 - shade) * blue)
130 let green = parseInt(color.slice(2, 4), 16)
131 let blue = parseInt(color.slice(4, 6), 16)
132
133 if (tint === 0) { // when primary color is in its rgb space
134 return [red, green, blue].join(',')
135 } else {
136 red += Math.round(tint * (255 - red))
137 green += Math.round(tint * (255 - green))
138 blue += Math.round(tint * (255 - blue))
139 161
140 red = red.toString(16) 162 red = red.toString(16)
141 green = green.toString(16) 163 green = green.toString(16)
...@@ -143,48 +165,31 @@ export default { ...@@ -143,48 +165,31 @@ export default {
143 165
144 return `#${red}${green}${blue}` 166 return `#${red}${green}${blue}`
145 } 167 }
146 }
147
148 const shadeColor = (color, shade) => {
149 let red = parseInt(color.slice(0, 2), 16)
150 let green = parseInt(color.slice(2, 4), 16)
151 let blue = parseInt(color.slice(4, 6), 16)
152
153 red = Math.round((1 - shade) * red)
154 green = Math.round((1 - shade) * green)
155 blue = Math.round((1 - shade) * blue)
156
157 red = red.toString(16)
158 green = green.toString(16)
159 blue = blue.toString(16)
160 168
161 return `#${red}${green}${blue}` 169 const clusters = [theme]
162 } 170 for (let i = 0; i <= 9; i++) {
163 171 clusters.push(tintColor(theme, Number((i / 10).toFixed(2))))
164 const clusters = [theme] 172 }
165 for (let i = 0; i <= 9; i++) { 173 clusters.push(shadeColor(theme, 0.1))
166 clusters.push(tintColor(theme, Number((i / 10).toFixed(2)))) 174 return clusters
167 } 175 }
168 clusters.push(shadeColor(theme, 0.1))
169 return clusters
170 } 176 }
171 } 177 }
172 }
173 </script> 178 </script>
174 179
175 <style> 180 <style>
176 .theme-message, 181 .theme-message,
177 .theme-picker-dropdown { 182 .theme-picker-dropdown {
178 z-index: 99999 !important; 183 z-index: 99999 !important;
179 } 184 }
180 185
181 .theme-picker .el-color-picker__trigger { 186 .theme-picker .el-color-picker__trigger {
182 height: 26px !important; 187 height: 26px !important;
183 width: 26px !important; 188 width: 26px !important;
184 padding: 2px; 189 padding: 2px;
185 } 190 }
186 191
187 .theme-picker-dropdown .el-color-dropdown__link-btn { 192 .theme-picker-dropdown .el-color-dropdown__link-btn {
188 display: none; 193 display: none;
189 } 194 }
190 </style> 195 </style>
......
1 <!--
2 * @Description:
3 * @Autor: renchao
4 * @LastEditTime: 2023-07-25 16:08:48
5 -->
1 <template> 6 <template>
2 <el-image-viewer :on-close="closeViewer" :url-list="urlList"> 7 <el-image-viewer :on-close="closeViewer" :url-list="urlList">
3 </el-image-viewer> 8 </el-image-viewer>
4 </template> 9 </template>
5 <script> 10 <script>
6 import ElImageViewer from 'element-ui/packages/image/src/image-viewer' 11 import ElImageViewer from 'element-ui/packages/image/src/image-viewer'
7 export default { 12 export default {
8 components: { 13 components: {
9 ElImageViewer, 14 ElImageViewer,
10 }, 15 },
11 props: { 16 props: {
12 urlList: { 17 urlList: {
13 type: Array, 18 type: Array,
14 default: function () { 19 default: function () {
15 return [] 20 return []
16 } 21 }
17 }
18 },
19 data () {
20 return {
21 wrapperElem: null
22 }
23 },
24 mounted () {
25 this.$nextTick(() => {
26 let wrapper = document.getElementsByClassName(
27 'el-image-viewer__actions__inner'
28 )
29 let downImg = document.createElement('i')
30 downImg.setAttribute('class', 'el-icon-download')
31 wrapper[0].appendChild(downImg)
32 if (wrapper.length > 0) {
33 this.wrapperElem = wrapper[0]
34 this.wrapperElem.addEventListener('click', this.hideCusBtn)
35 } 22 }
36 })
37 },
38 methods: {
39 /**
40 * @description: closeViewer
41 * @author: renchao
42 */
43 closeViewer () {
44 this.$emit('close-viewer')
45 }, 23 },
46 /** 24 data () {
47 * @description: hideCusBtn 25 return {
48 * @param {*} e 26 wrapperElem: null
49 * @author: renchao
50 */
51 hideCusBtn (e) {
52 let className = e.target.className
53 if (className === 'el-icon-download') {
54 let imgUrl = document.getElementsByClassName(
55 'el-image-viewer__canvas'
56 )[0].children[0].src
57 this.downloadImage(imgUrl)
58 } 27 }
59 }, 28 },
60 /** 29 mounted () {
61 * @description: downloadImage 30 this.$nextTick(() => {
62 * @param {*} imgUrl 31 let wrapper = document.getElementsByClassName(
63 * @author: renchao 32 'el-image-viewer__actions__inner'
64 */ 33 )
65 downloadImage (imgUrl) { 34 let downImg = document.createElement('i')
66 let tmpArr = imgUrl.split('/') 35 downImg.setAttribute('class', 'el-icon-download')
67 let fileName = tmpArr[tmpArr.length - 1] 36 wrapper[0].appendChild(downImg)
68 window.URL = window.URL || window.webkitURL 37 if (wrapper.length > 0) {
69 let xhr = new XMLHttpRequest() 38 this.wrapperElem = wrapper[0]
70 xhr.open('get', imgUrl, true) 39 this.wrapperElem.addEventListener('click', this.hideCusBtn)
71 xhr.responseType = 'blob' 40 }
72 xhr.onload = function () { 41 })
73 if (this.status == 200) { 42 },
74 //得到一个blob对象 43 methods: {
75 let blob = this.response 44 /**
76 let fileUrl = window.URL.createObjectURL(blob) 45 * @description: closeViewer
77 let a = document.createElement('a') 46 * @author: renchao
78 ; (document.body || document.documentElement).appendChild(a) 47 */
79 a.href = fileUrl 48 closeViewer () {
80 if ('download' in a) { 49 this.$emit('close-viewer')
81 a.download = fileName 50 },
82 } else { 51 /**
83 a.setAttribute('download', fileName) 52 * @description: hideCusBtn
53 * @param {*} e
54 * @author: renchao
55 */
56 hideCusBtn (e) {
57 let className = e.target.className
58 if (className === 'el-icon-download') {
59 let imgUrl = document.getElementsByClassName(
60 'el-image-viewer__canvas'
61 )[0].children[0].src
62 this.downloadImage(imgUrl)
63 }
64 },
65 /**
66 * @description: downloadImage
67 * @param {*} imgUrl
68 * @author: renchao
69 */
70 downloadImage (imgUrl) {
71 let tmpArr = imgUrl.split('/')
72 let fileName = tmpArr[tmpArr.length - 1]
73 window.URL = window.URL || window.webkitURL
74 let xhr = new XMLHttpRequest()
75 xhr.open('get', imgUrl, true)
76 xhr.responseType = 'blob'
77 xhr.onload = function () {
78 if (this.status == 200) {
79 //得到一个blob对象
80 let blob = this.response
81 let fileUrl = window.URL.createObjectURL(blob)
82 let a = document.createElement('a')
83 ; (document.body || document.documentElement).appendChild(a)
84 a.href = fileUrl
85 if ('download' in a) {
86 a.download = fileName
87 } else {
88 a.setAttribute('download', fileName)
89 }
90 a.target = '_self'
91 a.click()
92 a.remove()
84 } 93 }
85 a.target = '_self'
86 a.click()
87 a.remove()
88 } 94 }
89 } 95 xhr.send()
90 xhr.send() 96 },
91 }, 97 },
92 }, 98 }
93 }
94 </script> 99 </script>
95 100
96 <style lang="scss" scoped> 101 <style lang="scss" scoped>
97 /deep/ .el-image-viewer__close { 102 /deep/ .el-image-viewer__close {
98 color: #ffffff; 103 color: #ffffff;
99 } 104 }
100 </style> 105 </style>
......
1 <!--
2 * @Description:
3 * @Autor: renchao
4 * @LastEditTime: 2023-07-25 16:09:44
5 -->
1 <template> 6 <template>
2 <transition name="msgbox-fade"> 7 <transition name="msgbox-fade">
3 <div class="ls-mask" v-if="myShow"> 8 <div class="ls-mask" v-if="myShow">
......
1 <!--
2 * @Description:
3 * @Autor: renchao
4 * @LastEditTime: 2023-07-25 16:10:52
5 -->
1 <template> 6 <template>
2 <div class="app-wrapper"> 7 <div class="app-wrapper">
3 <navbar /> 8 <navbar />
...@@ -11,59 +16,59 @@ ...@@ -11,59 +16,59 @@
11 </div> 16 </div>
12 </template> 17 </template>
13 <script> 18 <script>
14 import { AppMain, Navbar, Sidebar, TagsView } from './components' 19 import { AppMain, Navbar, Sidebar, TagsView } from './components'
15 import ResizeMixin from './mixin/ResizeHandler' 20 import ResizeMixin from './mixin/ResizeHandler'
16 import { mapState } from 'vuex' 21 import { mapState } from 'vuex'
17 export default { 22 export default {
18 name: 'Layout', 23 name: 'Layout',
19 components: { 24 components: {
20 AppMain, 25 AppMain,
21 Navbar, 26 Navbar,
22 Sidebar, 27 Sidebar,
23 TagsView 28 TagsView
24 }, 29 },
25 mixins: [ResizeMixin], 30 mixins: [ResizeMixin],
26 computed: { 31 computed: {
27 ...mapState({ 32 ...mapState({
28 sidebar: state => state.app.sidebar, 33 sidebar: state => state.app.sidebar,
29 needTagsView: state => state.settings.tagsView, 34 needTagsView: state => state.settings.tagsView,
30 fixedHeader: state => state.settings.fixedHeader 35 fixedHeader: state => state.settings.fixedHeader
31 }) 36 })
37 }
32 } 38 }
33 }
34 </script> 39 </script>
35 <style lang="scss" scoped> 40 <style lang="scss" scoped>
36 @import "~@/styles/mixin.scss"; 41 @import "~@/styles/mixin.scss";
37 42
38 .app-wrapper { 43 .app-wrapper {
39 @include clearfix; 44 @include clearfix;
40 position: relative; 45 position: relative;
41 height: 100%; 46 height: 100%;
42 width: 100%; 47 width: 100%;
43 48
44 &.mobile.openSidebar { 49 &.mobile.openSidebar {
45 position: fixed; 50 position: fixed;
46 top: 0; 51 top: 0;
52 }
47 } 53 }
48 }
49 54
50 .drawer-bg { 55 .drawer-bg {
51 background: #000; 56 background: #000;
52 opacity: 0.3; 57 opacity: 0.3;
53 width: 100%; 58 width: 100%;
54 top: 0; 59 top: 0;
55 height: 100%; 60 height: 100%;
56 position: absolute; 61 position: absolute;
57 z-index: 999; 62 z-index: 999;
58 } 63 }
59 64
60 .fixed-header { 65 .fixed-header {
61 width: 100%; 66 width: 100%;
62 transition: width 0.28s; 67 transition: width 0.28s;
63 } 68 }
64 69
65 .el-dropdown-menu--small { 70 .el-dropdown-menu--small {
66 padding: 0; 71 padding: 0;
67 width: 5px; 72 width: 5px;
68 } 73 }
69 </style> 74 </style>
......
1 <!-- 1 <!--
2 * @Description: 2 * @Description:
3 * @Autor: renchao 3 * @Autor: renchao
4 * @LastEditTime: 2023-07-24 09:39:34 4 * @LastEditTime: 2023-07-25 16:15:39
5 --> 5 -->
6 <template> 6 <template>
7 <div class="container"> 7 <div class="container">
...@@ -158,7 +158,6 @@ ...@@ -158,7 +158,6 @@
158 this.fresh++; 158 this.fresh++;
159 //获取单元对应的所有表单信息 159 //获取单元对应的所有表单信息
160 this.tabList = res.result; 160 this.tabList = res.result;
161 console.log(res.result, 'res.result');
162 //默认加载第一个表单信息 161 //默认加载第一个表单信息
163 let arr = res.result.filter(item => item.defaultForm) 162 let arr = res.result.filter(item => item.defaultForm)
164 if (arr.length > 0) { 163 if (arr.length > 0) {
......
1 <!-- 1 <!--
2 * @Description: 2 * @Description:
3 * @Autor: renchao 3 * @Autor: renchao
4 * @LastEditTime: 2023-06-09 16:55:31 4 * @LastEditTime: 2023-07-25 16:15:46
5 --> 5 -->
6 <template> 6 <template>
7 <div class="container"> 7 <div class="container">
...@@ -125,7 +125,13 @@ ...@@ -125,7 +125,13 @@
125 //获取单元对应的所有表单信息 125 //获取单元对应的所有表单信息
126 this.tabList = res.result; 126 this.tabList = res.result;
127 //默认加载第一个表单信息 127 //默认加载第一个表单信息
128 this.tabName = res.result[0].value; 128 //默认加载第一个表单信息
129 let arr = res.result.filter(item => item.defaultForm)
130 if (arr.length > 0) {
131 this.tabName = arr[0].value;
132 } else {
133 this.tabName = res.result[0].value;
134 }
129 this.ableOperation = this.tabList[0].ableOperation 135 this.ableOperation = this.tabList[0].ableOperation
130 //批量操作无分屏按钮 136 //批量操作无分屏按钮
131 if (index != null) { 137 if (index != null) {
......