|
|
@ -55,7 +55,7 @@
|
|||
<div
|
||||
style="
|
||||
width: 230px;
|
||||
background: linear-gradient(180deg, #3370ff 0%, #7f3bf5 100%);
|
||||
background: linear-gradient(180deg, #3370FF 0%, #7f3bf5 100%);
|
||||
-webkit-background-clip: text;
|
||||
font-size: 24px;
|
||||
-webkit-text-fill-color: transparent;
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
"pinia": "^2.1.6",
|
||||
"pinyin-pro": "^3.18.2",
|
||||
"screenfull": "^6.0.2",
|
||||
"use-element-plus-theme": "^0.0.5",
|
||||
"vue": "^3.3.4",
|
||||
"vue-clipboard3": "^2.0.0",
|
||||
"vue-i18n": "^9.13.1",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
import { Result } from '@/request/Result'
|
||||
import { get, post, del, put } from '@/request/index'
|
||||
import type { Ref } from 'vue'
|
||||
const prefix = '/display'
|
||||
|
||||
/**
|
||||
* 查看外观设置
|
||||
*/
|
||||
const getThemeInfo: () => Promise<Result<any>> = () => {
|
||||
return get(`${prefix}/info`)
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新外观设置
|
||||
* @param 参数
|
||||
* * formData {
|
||||
* theme
|
||||
* icon
|
||||
* loginLogo
|
||||
* loginImage
|
||||
* title
|
||||
* slogan
|
||||
* }
|
||||
*/
|
||||
const postThemeInfo: (data: any, loading?: Ref<boolean>) => Promise<Result<boolean>> = (
|
||||
data,
|
||||
loading
|
||||
) => {
|
||||
return post(`${prefix}/update`, data, undefined, loading)
|
||||
}
|
||||
|
||||
export default {
|
||||
getThemeInfo,
|
||||
postThemeInfo
|
||||
}
|
||||
|
Before Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 8.0 KiB |
|
|
@ -0,0 +1,20 @@
|
|||
<svg width="122" height="36" viewBox="0 0 122 36" xmlns="http://www.w3.org/2000/svg" fill="#FF8800">
|
||||
<g clip-path="url(#clip0_5682_1471)" fill-rule="evenodd">
|
||||
<path d="M75.3094 19.0805V27.05H71.8274L71.8109 26.2436C70.5933 26.8762 69.4033 27.1925 68.2412 27.1923H67.8972C66.7033 27.1923 65.7546 26.7337 65.051 25.8166C64.5855 25.1007 64.342 24.2631 64.3513 23.4092V23.3143C64.3513 21.7489 64.9008 20.7092 65.9997 20.1953C66.4505 19.8949 67.5929 19.7447 69.4271 19.7447H71.3008V19.3058C71.3008 18.4045 71.1703 17.8867 70.9094 17.7523C70.6249 17.5388 70.1228 17.4321 69.4033 17.4321H65.6678L65.7312 14.2396L70.032 14.1233C72.5857 14.1233 74.1669 14.7558 74.7758 16.0208C75.1315 16.756 75.3094 17.7759 75.3094 19.0805ZM68.6032 22.3901C68.4844 22.5315 68.3597 22.9902 68.3597 23.3143C68.3597 24.0259 68.7234 24.3817 69.4508 24.3817C69.8855 24.3817 70.5022 24.2038 71.3008 23.848V22.1112C71.3008 22.1112 69.0361 21.875 68.6032 22.3901Z" fill="currentColor"/>
|
||||
<path d="M56.6308 27.3317L55.4162 15.1815L52.0028 27.3317H48.028L44.6928 15.1815L43.4348 27.3317L37.9399 27.2849L40.6207 9.35034H47.6212L50.0211 17.8845L52.4444 9.35034H59.281L62.0087 27.3317H56.6308Z" fill="currentColor"/>
|
||||
<path d="M85.3943 26.9654L83.5118 23.1105L81.6291 26.9654H77.2017L80.831 20.5778L77.3644 14.6084H81.6525L83.5118 18.2543L85.313 14.6084H89.6009L86.1576 20.5778L89.7637 26.9654H85.3943Z" fill="currentColor"/>
|
||||
<path d="M101.114 26.9656C101.029 26.8419 96.8966 20.1336 96.8966 20.1336L95.5396 22.2226V26.9656H90.9727V9.11621H95.5396V16.3526L99.7128 9.17639H104.477L99.514 17.1079L105.855 26.9656H101.114Z" fill="currentColor"/>
|
||||
<path d="M121.036 22.145C121.036 24.745 119.74 27.1282 115.097 27.1282H107.032V9.02689L113.203 8.90869C113.203 8.90869 116.858 8.74751 118.706 10.153C120.068 11.1885 120.515 13.0021 120.384 14.5197C120.254 16.0373 119.553 17.0129 118.405 17.727C119.979 18.354 121.036 19.5451 121.036 22.145ZM114.228 16.3325C115.766 16.3325 116.62 15.5559 116.62 14.45C116.62 13.2735 115.833 12.5837 114.228 12.5837L111.576 12.5906V16.3325H114.228ZM114.365 23.5374C116.497 23.5374 117.022 22.393 117.022 21.6316C117.022 20.4308 116.17 19.563 114.752 19.563H111.576V23.5374H114.365Z" fill="currentColor"/>
|
||||
<path d="M17.4213 26.7354H12.8296L11.1277 28.4372C11.028 28.5369 10.9601 28.6639 10.9326 28.8022C10.9051 28.9405 10.9193 29.0838 10.9732 29.2141C11.0272 29.3443 11.1185 29.4557 11.2358 29.534C11.353 29.6123 11.4908 29.6541 11.6318 29.6541H18.6192C18.7602 29.6541 18.898 29.6123 19.0153 29.534C19.1325 29.4557 19.2239 29.3443 19.2778 29.2141C19.3318 29.0838 19.3459 28.9405 19.3184 28.8022C19.2909 28.6639 19.223 28.5369 19.1233 28.4372L17.4213 26.7354Z" fill="currentColor"/>
|
||||
<path d="M30.04 13.3823H29.1348V19.7499H30.04C30.1305 19.7499 30.2201 19.732 30.3037 19.6974C30.3873 19.6628 30.4633 19.612 30.5273 19.548C30.5913 19.484 30.642 19.4081 30.6767 19.3244C30.7113 19.2408 30.7291 19.1512 30.7291 19.0607V14.0715C30.7291 13.8887 30.6565 13.7134 30.5273 13.5842C30.398 13.4549 30.2227 13.3823 30.04 13.3823Z" fill="currentColor"/>
|
||||
<path d="M1.92296 13.3823H1.01776C0.834985 13.3823 0.659698 13.4549 0.530458 13.5842C0.401219 13.7134 0.328613 13.8887 0.328613 14.0715V19.0607C0.328611 19.1512 0.346435 19.2408 0.381067 19.3244C0.415699 19.4081 0.466461 19.484 0.530455 19.548C0.594448 19.612 0.670419 19.6628 0.754031 19.6974C0.837643 19.732 0.927258 19.7499 1.01776 19.7499H1.92296V13.3823Z" fill="currentColor"/>
|
||||
<path d="M19.0238 14.2251C18.682 14.2251 18.3541 14.3609 18.1124 14.6026C17.8707 14.8443 17.7349 15.1722 17.7349 15.514V16.4382C17.7349 16.7801 17.8707 17.108 18.1124 17.3497C18.3541 17.5914 18.682 17.7272 19.0239 17.7272C19.3657 17.7272 19.6936 17.5914 19.9353 17.3497C20.1771 17.108 20.3129 16.7801 20.3129 16.4382V15.5141C20.3129 15.3448 20.2796 15.1772 20.2148 15.0208C20.15 14.8644 20.055 14.7223 19.9353 14.6026C19.8156 14.4829 19.6735 14.388 19.5171 14.3232C19.3607 14.2584 19.1931 14.2251 19.0238 14.2251Z" fill="currentColor"/>
|
||||
<path d="M12.3012 14.2251C11.9593 14.2251 11.6315 14.3609 11.3897 14.6026C11.148 14.8443 11.0122 15.1722 11.0122 15.514V16.4382C11.0122 16.7801 11.148 17.108 11.3897 17.3497C11.6315 17.5914 11.9593 17.7272 12.3012 17.7272C12.6431 17.7272 12.9709 17.5914 13.2127 17.3497C13.4544 17.108 13.5902 16.7801 13.5902 16.4382V15.5141C13.5902 15.3448 13.5569 15.1772 13.4921 15.0208C13.4273 14.8644 13.3324 14.7223 13.2127 14.6026C13.093 14.4829 12.9509 14.388 12.7945 14.3232C12.6381 14.2584 12.4704 14.2251 12.3012 14.2251Z" fill="currentColor"/>
|
||||
<path d="M23.3607 6.91333H7.69709C6.3139 6.91489 4.98782 7.46505 4.00976 8.44311C3.0317 9.42117 2.48154 10.7473 2.47998 12.1304V20.9612C2.48154 22.3444 3.03169 23.6705 4.00975 24.6486C4.98781 25.6266 6.3139 26.1768 7.69709 26.1784H23.3607C24.7439 26.1768 26.07 25.6267 27.0481 24.6486C28.0262 23.6705 28.5764 22.3444 28.5779 20.9612V12.1304C28.5763 10.7472 28.0262 9.42115 27.0481 8.44309C26.07 7.46503 24.7439 6.91487 23.3607 6.91333ZM23.7988 20.9085C23.7988 21.1577 23.6998 21.3968 23.5235 21.573C23.3473 21.7492 23.1083 21.8482 22.859 21.8482H15.2189C14.0629 21.8482 12.9263 22.1453 11.9181 22.711L9.355 24.1492V21.8483H8.19882C7.94958 21.8483 7.71055 21.7493 7.53432 21.573C7.35808 21.3968 7.25907 21.1578 7.25906 20.9085V11.547C7.25907 11.2978 7.35808 11.0588 7.53432 10.8825C7.71056 10.7063 7.94958 10.6073 8.19882 10.6073H22.859C23.1082 10.6073 23.3472 10.7063 23.5235 10.8825C23.6997 11.0588 23.7987 11.2978 23.7987 11.5471L23.7988 20.9085Z" fill="currentColor"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_5682_1471">
|
||||
<rect width="121" height="36" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.4 KiB |
|
|
@ -0,0 +1,64 @@
|
|||
<svg width="122" height="36" viewBox="0 0 122 36" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_5734_851)">
|
||||
<path d="M75.3094 19.0802V27.0498H71.8274L71.8109 26.2433C70.5933 26.876 69.4033 27.1922 68.2412 27.1921H67.8972C66.7033 27.1921 65.7546 26.7335 65.051 25.8164C64.5855 25.1005 64.342 24.2629 64.3513 23.409V23.314C64.3513 21.7486 64.9008 20.7089 65.9997 20.195C66.4505 19.8947 67.5929 19.7445 69.4271 19.7444H71.3008V19.3056C71.3008 18.4043 71.1703 17.8865 70.9094 17.752C70.6249 17.5385 70.1228 17.4318 69.4033 17.4318H65.6678L65.7312 14.2393L70.032 14.123C72.5857 14.123 74.1669 14.7555 74.7758 16.0206C75.1315 16.7558 75.3094 17.7757 75.3094 19.0802ZM68.6032 22.3899C68.4844 22.5313 68.3597 22.99 68.3597 23.314C68.3597 24.0256 68.7234 24.3814 69.4508 24.3814C69.8855 24.3814 70.5022 24.2035 71.3008 23.8478V22.111C71.3008 22.111 69.0361 21.8747 68.6032 22.3899Z" fill="url(#paint0_linear_5734_851)"/>
|
||||
<path d="M56.6308 27.3319L55.4162 15.1817L52.0028 27.3319H48.028L44.6928 15.1817L43.4348 27.3319L37.9399 27.2851L40.6207 9.35059H47.6212L50.0211 17.8847L52.4444 9.35059H59.281L62.0087 27.3319H56.6308Z" fill="url(#paint1_linear_5734_851)"/>
|
||||
<path d="M85.3943 26.9654L83.5118 23.1105L81.6291 26.9654H77.2017L80.831 20.5778L77.3644 14.6084H81.6525L83.5118 18.2543L85.313 14.6084H89.6009L86.1576 20.5778L89.7637 26.9654H85.3943Z" fill="url(#paint2_linear_5734_851)"/>
|
||||
<path d="M101.114 26.9656C101.029 26.8419 96.8966 20.1336 96.8966 20.1336L95.5396 22.2226V26.9656H90.9727V9.11621H95.5396V16.3526L99.7128 9.17639H104.477L99.514 17.1079L105.855 26.9656H101.114Z" fill="url(#paint3_linear_5734_851)"/>
|
||||
<path d="M121.036 22.1453C121.036 24.7452 119.74 27.1284 115.097 27.1284H107.032V9.02713L113.203 8.90893C113.203 8.90893 116.858 8.74776 118.706 10.1533C120.068 11.1888 120.515 13.0023 120.384 14.5199C120.254 16.0375 119.553 17.0132 118.405 17.7272C119.979 18.3542 121.036 19.5453 121.036 22.1453ZM114.228 16.3327C115.766 16.3327 116.62 15.5561 116.62 14.4502C116.62 13.2738 115.833 12.5839 114.228 12.5839L111.576 12.5909V16.3327H114.228ZM114.365 23.5376C116.497 23.5376 117.022 22.3933 117.022 21.6318C117.022 20.4311 116.17 19.5633 114.752 19.5633H111.576V23.5376H114.365Z" fill="url(#paint4_linear_5734_851)"/>
|
||||
<path d="M17.4213 26.7354H12.8296L11.1277 28.4372C11.028 28.5369 10.9601 28.6639 10.9326 28.8022C10.9051 28.9405 10.9193 29.0838 10.9732 29.2141C11.0272 29.3443 11.1185 29.4557 11.2358 29.534C11.353 29.6123 11.4908 29.6541 11.6318 29.6541H18.6192C18.7602 29.6541 18.898 29.6123 19.0153 29.534C19.1325 29.4557 19.2239 29.3443 19.2778 29.2141C19.3318 29.0838 19.3459 28.9405 19.3184 28.8022C19.2909 28.6639 19.223 28.5369 19.1233 28.4372L17.4213 26.7354Z" fill="url(#paint5_linear_5734_851)"/>
|
||||
<path d="M30.04 13.3823H29.1348V19.7499H30.04C30.1305 19.7499 30.2201 19.732 30.3037 19.6974C30.3873 19.6628 30.4633 19.612 30.5273 19.548C30.5913 19.484 30.642 19.4081 30.6767 19.3244C30.7113 19.2408 30.7291 19.1512 30.7291 19.0607V14.0715C30.7291 13.8887 30.6565 13.7134 30.5273 13.5842C30.398 13.4549 30.2227 13.3823 30.04 13.3823Z" fill="url(#paint6_linear_5734_851)"/>
|
||||
<path d="M1.92296 13.3823H1.01776C0.834985 13.3823 0.659698 13.4549 0.530458 13.5842C0.401219 13.7134 0.328613 13.8887 0.328613 14.0715V19.0607C0.328611 19.1512 0.346435 19.2408 0.381067 19.3244C0.415699 19.4081 0.466461 19.484 0.530455 19.548C0.594448 19.612 0.670419 19.6628 0.754031 19.6974C0.837643 19.732 0.927258 19.7499 1.01776 19.7499H1.92296V13.3823Z" fill="url(#paint7_linear_5734_851)"/>
|
||||
<path d="M19.0238 14.2251C18.682 14.2251 18.3541 14.3609 18.1124 14.6026C17.8707 14.8443 17.7349 15.1722 17.7349 15.514V16.4382C17.7349 16.7801 17.8707 17.108 18.1124 17.3497C18.3541 17.5914 18.682 17.7272 19.0239 17.7272C19.3657 17.7272 19.6936 17.5914 19.9353 17.3497C20.1771 17.108 20.3129 16.7801 20.3129 16.4382V15.5141C20.3129 15.3448 20.2796 15.1772 20.2148 15.0208C20.15 14.8644 20.055 14.7223 19.9353 14.6026C19.8156 14.4829 19.6735 14.388 19.5171 14.3232C19.3607 14.2584 19.1931 14.2251 19.0238 14.2251Z" fill="url(#paint8_linear_5734_851)"/>
|
||||
<path d="M12.3012 14.2251C11.9593 14.2251 11.6315 14.3609 11.3897 14.6026C11.148 14.8443 11.0122 15.1722 11.0122 15.514V16.4382C11.0122 16.7801 11.148 17.108 11.3897 17.3497C11.6315 17.5914 11.9593 17.7272 12.3012 17.7272C12.6431 17.7272 12.9709 17.5914 13.2127 17.3497C13.4544 17.108 13.5902 16.7801 13.5902 16.4382V15.5141C13.5902 15.3448 13.5569 15.1772 13.4921 15.0208C13.4273 14.8644 13.3324 14.7223 13.2127 14.6026C13.093 14.4829 12.9509 14.388 12.7945 14.3232C12.6381 14.2584 12.4704 14.2251 12.3012 14.2251Z" fill="url(#paint9_linear_5734_851)"/>
|
||||
<path d="M23.3607 6.91309H7.69709C6.3139 6.91465 4.98782 7.46481 4.00976 8.44287C3.0317 9.42092 2.48154 10.747 2.47998 12.1302V20.9609C2.48154 22.3441 3.03169 23.6702 4.00975 24.6483C4.98781 25.6264 6.3139 26.1766 7.69709 26.1781H23.3607C24.7439 26.1766 26.07 25.6264 27.0481 24.6483C28.0262 23.6703 28.5764 22.3442 28.5779 20.9609V12.1302C28.5763 10.747 28.0262 9.4209 27.0481 8.44284C26.07 7.46478 24.7439 6.91463 23.3607 6.91309ZM23.7988 20.9082C23.7988 21.1575 23.6998 21.3965 23.5235 21.5727C23.3473 21.749 23.1083 21.848 22.859 21.848H15.2189C14.0629 21.848 12.9263 22.1451 11.9181 22.7108L9.355 24.149V21.848H8.19882C7.94958 21.848 7.71055 21.749 7.53432 21.5728C7.35808 21.3966 7.25907 21.1575 7.25906 20.9083V11.5468C7.25907 11.2976 7.35808 11.0585 7.53432 10.8823C7.71056 10.7061 7.94958 10.6071 8.19882 10.6071H22.859C23.1082 10.6071 23.3472 10.7061 23.5235 10.8823C23.6997 11.0585 23.7987 11.2976 23.7987 11.5468L23.7988 20.9082Z" fill="url(#paint10_linear_5734_851)"/>
|
||||
</g>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_5734_851" x1="69.8304" y1="10.0003" x2="69.8304" y2="27.3566" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#3370FF"/>
|
||||
<stop offset="1" stop-color="#7F3BF5"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_5734_851" x1="49.9743" y1="10.5855" x2="49.9743" y2="27.4838" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#3370FF"/>
|
||||
<stop offset="1" stop-color="#7F3BF5"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint2_linear_5734_851" x1="83.4827" y1="9.95634" x2="83.4827" y2="26.918" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#3370FF"/>
|
||||
<stop offset="1" stop-color="#7F3BF5"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint3_linear_5734_851" x1="98.4139" y1="9.57325" x2="98.4139" y2="26.5967" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#3370FF"/>
|
||||
<stop offset="1" stop-color="#7F3BF5"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint4_linear_5734_851" x1="114.034" y1="9.05828" x2="114.034" y2="26.3934" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#3370FF"/>
|
||||
<stop offset="1" stop-color="#7F3BF5"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint5_linear_5734_851" x1="15.1255" y1="26.7354" x2="15.1255" y2="29.6542" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#3370FF"/>
|
||||
<stop offset="1" stop-color="#7F3BF5"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint6_linear_5734_851" x1="29.9319" y1="13.3823" x2="29.9319" y2="19.7499" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#3370FF"/>
|
||||
<stop offset="1" stop-color="#7F3BF5"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint7_linear_5734_851" x1="1.12576" y1="13.3823" x2="1.12576" y2="19.7499" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#3370FF"/>
|
||||
<stop offset="1" stop-color="#7F3BF5"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint8_linear_5734_851" x1="19.0238" y1="14.2251" x2="19.0238" y2="17.7273" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#3370FF"/>
|
||||
<stop offset="1" stop-color="#7F3BF5"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint9_linear_5734_851" x1="12.3012" y1="14.2251" x2="12.3012" y2="17.7273" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#3370FF"/>
|
||||
<stop offset="1" stop-color="#7F3BF5"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint10_linear_5734_851" x1="15.5289" y1="6.91309" x2="15.5289" y2="26.1782" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#3370FF"/>
|
||||
<stop offset="1" stop-color="#7F3BF5"/>
|
||||
</linearGradient>
|
||||
<clipPath id="clip0_5734_851">
|
||||
<rect width="121" height="36" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.9 KiB |
|
|
@ -0,0 +1 @@
|
|||
<svg id="图层_1" data-name="图层 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 232.4409 232.4409"><title>MaxKB</title><path class="cls-1" d="M128.4532,177H98.7785L87.78,187.9985a4.6069,4.6069,0,0,0,3.2576,7.8644h45.1569a4.6069,4.6069,0,0,0,3.2575-7.8644Z"/><path class="cls-1" d="M210.0008,90.7042h-5.85v41.1511h5.85a4.4537,4.4537,0,0,0,4.4537-4.4537V95.1579A4.4537,4.4537,0,0,0,210.0008,90.7042Z"/><path class="cls-1" d="M28.29,90.7042H22.44a4.4538,4.4538,0,0,0-4.4538,4.4537v32.2437a4.4538,4.4538,0,0,0,4.4538,4.4537h5.85Z"/><path class="cls-1" d="M138.8087,96.1512a8.33,8.33,0,0,0-8.33,8.33v5.9727a8.33,8.33,0,1,0,16.6607,0v-5.9727A8.33,8.33,0,0,0,138.8087,96.1512Z"/><path class="cls-1" d="M95.3622,96.1512a8.33,8.33,0,0,0-8.33,8.33v5.9727a8.33,8.33,0,1,0,16.6607,0v-5.9727A8.33,8.33,0,0,0,95.3622,96.1512Z"/><path class="cls-1" d="M166.8344,48.8968H65.6064A33.7544,33.7544,0,0,0,31.89,82.6131v57.07A33.7548,33.7548,0,0,0,65.6064,173.4h101.228a33.7549,33.7549,0,0,0,33.7168-33.7168v-57.07A33.7545,33.7545,0,0,0,166.8344,48.8968Zm2.831,90.4457a6.0733,6.0733,0,0,1-6.0732,6.0733H114.2168a43.5922,43.5922,0,0,0-21.3313,5.5757l-16.5647,9.2946v-14.87h-7.472a6.0733,6.0733,0,0,1-6.0733-6.0733v-60.5a6.0733,6.0733,0,0,1,6.0733-6.0733h94.7434a6.0733,6.0733,0,0,1,6.0732,6.0733Z"/></svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
|
|
@ -0,0 +1 @@
|
|||
<svg id="图层_1" data-name="图层 1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 232.4409 232.4409"><defs><style>.cls-1{fill:url(#未命名的渐变_7);}.cls-2{fill:url(#未命名的渐变_7-2);}.cls-3{fill:url(#未命名的渐变_7-3);}.cls-4{fill:url(#未命名的渐变_7-4);}.cls-5{fill:url(#未命名的渐变_7-5);}.cls-6{fill:url(#未命名的渐变_7-6);}</style><linearGradient id="未命名的渐变_7" x1="113.6159" y1="176.9998" x2="113.6159" y2="195.8629" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#3370FF"/><stop offset="1" stop-color="#7f3bf5"/></linearGradient><linearGradient id="未命名的渐变_7-2" x1="209.3027" y1="90.7042" x2="209.3027" y2="131.8553" xlink:href="#未命名的渐变_7"/><linearGradient id="未命名的渐变_7-3" x1="23.1384" y1="90.7042" x2="23.1384" y2="131.8553" xlink:href="#未命名的渐变_7"/><linearGradient id="未命名的渐变_7-4" x1="138.8087" y1="96.1512" x2="138.8087" y2="118.7847" xlink:href="#未命名的渐变_7"/><linearGradient id="未命名的渐变_7-5" x1="95.3622" y1="96.1512" x2="95.3622" y2="118.7847" xlink:href="#未命名的渐变_7"/><linearGradient id="未命名的渐变_7-6" x1="116.2206" y1="48.8968" x2="116.2206" y2="173.4002" xlink:href="#未命名的渐变_7"/></defs><title>MaxKB</title><path class="cls-1" d="M128.4532,177H98.7785L87.78,187.9985a4.6069,4.6069,0,0,0,3.2576,7.8644h45.1569a4.6069,4.6069,0,0,0,3.2575-7.8644Z"/><path class="cls-2" d="M210.0008,90.7042h-5.85v41.1511h5.85a4.4537,4.4537,0,0,0,4.4537-4.4537V95.1579A4.4537,4.4537,0,0,0,210.0008,90.7042Z"/><path class="cls-3" d="M28.29,90.7042H22.44a4.4538,4.4538,0,0,0-4.4538,4.4537v32.2437a4.4538,4.4538,0,0,0,4.4538,4.4537h5.85Z"/><path class="cls-4" d="M138.8087,96.1512a8.33,8.33,0,0,0-8.33,8.33v5.9727a8.33,8.33,0,1,0,16.6607,0v-5.9727A8.33,8.33,0,0,0,138.8087,96.1512Z"/><path class="cls-5" d="M95.3622,96.1512a8.33,8.33,0,0,0-8.33,8.33v5.9727a8.33,8.33,0,1,0,16.6607,0v-5.9727A8.33,8.33,0,0,0,95.3622,96.1512Z"/><path class="cls-6" d="M166.8344,48.8968H65.6064A33.7544,33.7544,0,0,0,31.89,82.6131v57.07A33.7548,33.7548,0,0,0,65.6064,173.4h101.228a33.7549,33.7549,0,0,0,33.7168-33.7168v-57.07A33.7545,33.7545,0,0,0,166.8344,48.8968Zm2.831,90.4457a6.0733,6.0733,0,0,1-6.0732,6.0733H114.2168a43.5922,43.5922,0,0,0-21.3313,5.5757l-16.5647,9.2946v-14.87h-7.472a6.0733,6.0733,0,0,1-6.0733-6.0733v-60.5a6.0733,6.0733,0,0,1,6.0733-6.0733h94.7434a6.0733,6.0733,0,0,1,6.0732,6.0733Z"/></svg>
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 770 KiB After Width: | Height: | Size: 770 KiB |
|
After Width: | Height: | Size: 647 KiB |
|
After Width: | Height: | Size: 683 KiB |
|
After Width: | Height: | Size: 602 KiB |
|
After Width: | Height: | Size: 626 KiB |
|
|
@ -23,8 +23,8 @@
|
|||
</el-icon>
|
||||
{{ data?.document_name }}
|
||||
</el-text>
|
||||
<div class="flex align-center" style="line-height: 32px;">
|
||||
<AppAvatar class="mr-8" shape="square" :size="18">
|
||||
<div class="flex align-center" style="line-height: 32px">
|
||||
<AppAvatar class="mr-8 avatar-blue" shape="square" :size="18">
|
||||
<img src="@/assets/icon_document.svg" style="width: 58%" alt="" />
|
||||
</AppAvatar>
|
||||
|
||||
|
|
@ -52,7 +52,7 @@ const props = defineProps({
|
|||
}
|
||||
@media only screen and (max-width: 768px) {
|
||||
.paragraph-source-card-height {
|
||||
height: 285px;
|
||||
}
|
||||
height: 285px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
<slot name="header">
|
||||
<div class="title flex align-center">
|
||||
<slot name="icon">
|
||||
<AppAvatar v-if="showIcon" class="mr-12" shape="square" :size="32">
|
||||
<AppAvatar v-if="showIcon" class="mr-12 avatar-blue" shape="square" :size="32">
|
||||
<img src="@/assets/icon_document.svg" style="width: 58%" alt="" />
|
||||
</AppAvatar>
|
||||
</slot>
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
<img src="@/assets/icon_web.svg" style="width: 58%" alt="" />
|
||||
</AppAvatar>
|
||||
|
||||
<AppAvatar v-else class="mr-12" shape="square" :size="32">
|
||||
<AppAvatar v-else class="mr-12 avatar-blue" shape="square" :size="32">
|
||||
<img src="@/assets/icon_document.svg" style="width: 58%" alt="" />
|
||||
</AppAvatar>
|
||||
</slot>
|
||||
|
|
|
|||
|
|
@ -955,7 +955,7 @@ export const iconMap: any = {
|
|||
])
|
||||
}
|
||||
},
|
||||
'app-minify': {
|
||||
'app-magnify': {
|
||||
iconReader: () => {
|
||||
return h('i', [
|
||||
h(
|
||||
|
|
@ -976,7 +976,7 @@ export const iconMap: any = {
|
|||
])
|
||||
}
|
||||
},
|
||||
'app-magnify': {
|
||||
'app-minify': {
|
||||
iconReader: () => {
|
||||
return h('i', [
|
||||
h(
|
||||
|
|
@ -1071,5 +1071,5 @@ export const iconMap: any = {
|
|||
)
|
||||
])
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ import InfiniteScroll from './infinite-scroll/index.vue'
|
|||
import AutoTooltip from './auto-tooltip/index.vue'
|
||||
import MdEditor from './markdown/MdEditor.vue'
|
||||
import MdPreview from './markdown/MdPreview.vue'
|
||||
import LogoFull from './logo/LogoFull.vue'
|
||||
import LogoIcon from './logo/LogoIcon.vue'
|
||||
|
||||
export default {
|
||||
install(app: App) {
|
||||
|
|
@ -42,5 +44,7 @@ export default {
|
|||
app.component(AutoTooltip.name, AutoTooltip)
|
||||
app.component(MdPreview.name, MdPreview)
|
||||
app.component(MdEditor.name, MdEditor)
|
||||
app.component(LogoFull.name, LogoFull)
|
||||
app.component(LogoIcon.name, LogoIcon)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
<template>
|
||||
<div class="login-form-container">
|
||||
<div class="login-title">
|
||||
<div class="logo text-center"><img src="@/assets/MaxKB-logo.svg" height="45" /></div>
|
||||
<div class="logo text-center">
|
||||
<LogoFull height="45px" />
|
||||
</div>
|
||||
<div class="sub-title text-center" v-if="subTitle">
|
||||
<el-text type="info">{{ subTitle }}</el-text>
|
||||
</div>
|
||||
|
|
@ -12,7 +14,6 @@
|
|||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
const defaultTitle = import.meta.env.VITE_APP_TITLE
|
||||
defineOptions({ name: 'LoginContainer' })
|
||||
defineProps({
|
||||
title: String,
|
||||
|
|
|
|||
|
|
@ -2,9 +2,8 @@
|
|||
<div class="login-warp flex-center">
|
||||
<div class="login-container w-full h-full">
|
||||
<el-row class="container w-full h-full">
|
||||
<!-- v-if="screenWidth && screenWidth >= 990" -->
|
||||
<el-col :xs="0" :sm="0" :md="10" :lg="10" :xl="10" class="left-container">
|
||||
<div class="login-image"></div>
|
||||
<div class="login-image" :style="loginImageStyle"></div>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="14" :lg="14" :xl="14" class="right-container flex-center">
|
||||
<slot></slot>
|
||||
|
|
@ -14,25 +13,43 @@
|
|||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
// import { ref, onMounted } from 'vue'
|
||||
// import type { Ref } from 'vue'
|
||||
import { computed } from 'vue'
|
||||
import { getThemeImg } from '@/utils/theme'
|
||||
import useStore from '@/stores'
|
||||
defineOptions({ name: 'LoginLayout' })
|
||||
// const screenWidth: Ref<number | null> = ref(null)
|
||||
// onMounted(() => {
|
||||
// screenWidth.value = document.body.clientWidth
|
||||
// window.onresize = () => {
|
||||
// return (() => {
|
||||
// screenWidth.value = document.body.clientWidth
|
||||
// })()
|
||||
// }
|
||||
// })
|
||||
const { user } = useStore()
|
||||
|
||||
const fileURL = computed(() => {
|
||||
if (user.themeInfo?.loginImage) {
|
||||
if (typeof user.themeInfo?.loginImage === 'string') {
|
||||
return user.themeInfo?.loginImage
|
||||
} else {
|
||||
return URL.createObjectURL(user.themeInfo?.loginImage)
|
||||
}
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
})
|
||||
|
||||
const loginImageStyle = computed(() => {
|
||||
if (user.themeInfo?.loginImage) {
|
||||
return {
|
||||
backgroundImage: `url(${fileURL.value})`
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
backgroundImage: `url(../src/assets/theme/${getThemeImg(user.themeInfo?.theme)}.jpg)`
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scope>
|
||||
.login-warp {
|
||||
height: 100vh;
|
||||
|
||||
.login-image {
|
||||
background: url(@/assets/login.jpg) no-repeat center;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
background-size: cover;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,95 @@
|
|||
<template>
|
||||
<img v-if="user.themeInfo?.loginLogo" :src="fileURL" alt="" height="45px" class="mr-8" />
|
||||
<template v-else>
|
||||
<svg
|
||||
v-if="!isDefaultTheme"
|
||||
viewBox="0 0 122 36"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
:height="height"
|
||||
:class="!isDefaultTheme ? 'custom-logo-color' : ''"
|
||||
>
|
||||
<g clip-path="url(#clip0_5682_1471)" fill-rule="evenodd">
|
||||
<path
|
||||
d="M75.3094 19.0805V27.05H71.8274L71.8109 26.2436C70.5933 26.8762 69.4033 27.1925 68.2412 27.1923H67.8972C66.7033 27.1923 65.7546 26.7337 65.051 25.8166C64.5855 25.1007 64.342 24.2631 64.3513 23.4092V23.3143C64.3513 21.7489 64.9008 20.7092 65.9997 20.1953C66.4505 19.8949 67.5929 19.7447 69.4271 19.7447H71.3008V19.3058C71.3008 18.4045 71.1703 17.8867 70.9094 17.7523C70.6249 17.5388 70.1228 17.4321 69.4033 17.4321H65.6678L65.7312 14.2396L70.032 14.1233C72.5857 14.1233 74.1669 14.7558 74.7758 16.0208C75.1315 16.756 75.3094 17.7759 75.3094 19.0805ZM68.6032 22.3901C68.4844 22.5315 68.3597 22.9902 68.3597 23.3143C68.3597 24.0259 68.7234 24.3817 69.4508 24.3817C69.8855 24.3817 70.5022 24.2038 71.3008 23.848V22.1112C71.3008 22.1112 69.0361 21.875 68.6032 22.3901Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
d="M56.6308 27.3317L55.4162 15.1815L52.0028 27.3317H48.028L44.6928 15.1815L43.4348 27.3317L37.9399 27.2849L40.6207 9.35034H47.6212L50.0211 17.8845L52.4444 9.35034H59.281L62.0087 27.3317H56.6308Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
d="M85.3943 26.9654L83.5118 23.1105L81.6291 26.9654H77.2017L80.831 20.5778L77.3644 14.6084H81.6525L83.5118 18.2543L85.313 14.6084H89.6009L86.1576 20.5778L89.7637 26.9654H85.3943Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
d="M101.114 26.9656C101.029 26.8419 96.8966 20.1336 96.8966 20.1336L95.5396 22.2226V26.9656H90.9727V9.11621H95.5396V16.3526L99.7128 9.17639H104.477L99.514 17.1079L105.855 26.9656H101.114Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
d="M121.036 22.145C121.036 24.745 119.74 27.1282 115.097 27.1282H107.032V9.02689L113.203 8.90869C113.203 8.90869 116.858 8.74751 118.706 10.153C120.068 11.1885 120.515 13.0021 120.384 14.5197C120.254 16.0373 119.553 17.0129 118.405 17.727C119.979 18.354 121.036 19.5451 121.036 22.145ZM114.228 16.3325C115.766 16.3325 116.62 15.5559 116.62 14.45C116.62 13.2735 115.833 12.5837 114.228 12.5837L111.576 12.5906V16.3325H114.228ZM114.365 23.5374C116.497 23.5374 117.022 22.393 117.022 21.6316C117.022 20.4308 116.17 19.563 114.752 19.563H111.576V23.5374H114.365Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
d="M17.4213 26.7354H12.8296L11.1277 28.4372C11.028 28.5369 10.9601 28.6639 10.9326 28.8022C10.9051 28.9405 10.9193 29.0838 10.9732 29.2141C11.0272 29.3443 11.1185 29.4557 11.2358 29.534C11.353 29.6123 11.4908 29.6541 11.6318 29.6541H18.6192C18.7602 29.6541 18.898 29.6123 19.0153 29.534C19.1325 29.4557 19.2239 29.3443 19.2778 29.2141C19.3318 29.0838 19.3459 28.9405 19.3184 28.8022C19.2909 28.6639 19.223 28.5369 19.1233 28.4372L17.4213 26.7354Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
d="M30.04 13.3823H29.1348V19.7499H30.04C30.1305 19.7499 30.2201 19.732 30.3037 19.6974C30.3873 19.6628 30.4633 19.612 30.5273 19.548C30.5913 19.484 30.642 19.4081 30.6767 19.3244C30.7113 19.2408 30.7291 19.1512 30.7291 19.0607V14.0715C30.7291 13.8887 30.6565 13.7134 30.5273 13.5842C30.398 13.4549 30.2227 13.3823 30.04 13.3823Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
d="M1.92296 13.3823H1.01776C0.834985 13.3823 0.659698 13.4549 0.530458 13.5842C0.401219 13.7134 0.328613 13.8887 0.328613 14.0715V19.0607C0.328611 19.1512 0.346435 19.2408 0.381067 19.3244C0.415699 19.4081 0.466461 19.484 0.530455 19.548C0.594448 19.612 0.670419 19.6628 0.754031 19.6974C0.837643 19.732 0.927258 19.7499 1.01776 19.7499H1.92296V13.3823Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
d="M19.0238 14.2251C18.682 14.2251 18.3541 14.3609 18.1124 14.6026C17.8707 14.8443 17.7349 15.1722 17.7349 15.514V16.4382C17.7349 16.7801 17.8707 17.108 18.1124 17.3497C18.3541 17.5914 18.682 17.7272 19.0239 17.7272C19.3657 17.7272 19.6936 17.5914 19.9353 17.3497C20.1771 17.108 20.3129 16.7801 20.3129 16.4382V15.5141C20.3129 15.3448 20.2796 15.1772 20.2148 15.0208C20.15 14.8644 20.055 14.7223 19.9353 14.6026C19.8156 14.4829 19.6735 14.388 19.5171 14.3232C19.3607 14.2584 19.1931 14.2251 19.0238 14.2251Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
d="M12.3012 14.2251C11.9593 14.2251 11.6315 14.3609 11.3897 14.6026C11.148 14.8443 11.0122 15.1722 11.0122 15.514V16.4382C11.0122 16.7801 11.148 17.108 11.3897 17.3497C11.6315 17.5914 11.9593 17.7272 12.3012 17.7272C12.6431 17.7272 12.9709 17.5914 13.2127 17.3497C13.4544 17.108 13.5902 16.7801 13.5902 16.4382V15.5141C13.5902 15.3448 13.5569 15.1772 13.4921 15.0208C13.4273 14.8644 13.3324 14.7223 13.2127 14.6026C13.093 14.4829 12.9509 14.388 12.7945 14.3232C12.6381 14.2584 12.4704 14.2251 12.3012 14.2251Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
d="M23.3607 6.91333H7.69709C6.3139 6.91489 4.98782 7.46505 4.00976 8.44311C3.0317 9.42117 2.48154 10.7473 2.47998 12.1304V20.9612C2.48154 22.3444 3.03169 23.6705 4.00975 24.6486C4.98781 25.6266 6.3139 26.1768 7.69709 26.1784H23.3607C24.7439 26.1768 26.07 25.6267 27.0481 24.6486C28.0262 23.6705 28.5764 22.3444 28.5779 20.9612V12.1304C28.5763 10.7472 28.0262 9.42115 27.0481 8.44309C26.07 7.46503 24.7439 6.91487 23.3607 6.91333ZM23.7988 20.9085C23.7988 21.1577 23.6998 21.3968 23.5235 21.573C23.3473 21.7492 23.1083 21.8482 22.859 21.8482H15.2189C14.0629 21.8482 12.9263 22.1453 11.9181 22.711L9.355 24.1492V21.8483H8.19882C7.94958 21.8483 7.71055 21.7493 7.53432 21.573C7.35808 21.3968 7.25907 21.1578 7.25906 20.9085V11.547C7.25907 11.2978 7.35808 11.0588 7.53432 10.8825C7.71056 10.7063 7.94958 10.6073 8.19882 10.6073H22.859C23.1082 10.6073 23.3472 10.7063 23.5235 10.8825C23.6997 11.0588 23.7987 11.2978 23.7987 11.5471L23.7988 20.9085Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
<img v-else src="@/assets/logo/MaxKB-logo.svg" :height="height" />
|
||||
</template>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import useStore from '@/stores'
|
||||
defineOptions({ name: 'LogoFull' })
|
||||
|
||||
defineProps({
|
||||
height: {
|
||||
type: String,
|
||||
default: '36px'
|
||||
}
|
||||
})
|
||||
const { user } = useStore()
|
||||
const isDefaultTheme = computed(() => {
|
||||
return user.isDefaultTheme()
|
||||
})
|
||||
|
||||
const fileURL = computed(() => {
|
||||
if (user.themeInfo?.loginLogo) {
|
||||
if (typeof user.themeInfo?.loginLogo === 'string') {
|
||||
return user.themeInfo?.loginLogo
|
||||
} else {
|
||||
return URL.createObjectURL(user.themeInfo?.loginLogo)
|
||||
}
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.custom-logo-color {
|
||||
path {
|
||||
fill: var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
<template>
|
||||
<svg
|
||||
v-if="!isDefaultTheme"
|
||||
:class="!isDefaultTheme ? 'custom-logo-color' : ''"
|
||||
:height="height"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 232.4409 232.4409"
|
||||
>
|
||||
<title>MaxKB</title>
|
||||
<path
|
||||
class="cls-1"
|
||||
d="M128.4532,177H98.7785L87.78,187.9985a4.6069,4.6069,0,0,0,3.2576,7.8644h45.1569a4.6069,4.6069,0,0,0,3.2575-7.8644Z"
|
||||
/>
|
||||
<path
|
||||
class="cls-1"
|
||||
d="M210.0008,90.7042h-5.85v41.1511h5.85a4.4537,4.4537,0,0,0,4.4537-4.4537V95.1579A4.4537,4.4537,0,0,0,210.0008,90.7042Z"
|
||||
/>
|
||||
<path
|
||||
class="cls-1"
|
||||
d="M28.29,90.7042H22.44a4.4538,4.4538,0,0,0-4.4538,4.4537v32.2437a4.4538,4.4538,0,0,0,4.4538,4.4537h5.85Z"
|
||||
/>
|
||||
<path
|
||||
class="cls-1"
|
||||
d="M138.8087,96.1512a8.33,8.33,0,0,0-8.33,8.33v5.9727a8.33,8.33,0,1,0,16.6607,0v-5.9727A8.33,8.33,0,0,0,138.8087,96.1512Z"
|
||||
/>
|
||||
<path
|
||||
class="cls-1"
|
||||
d="M95.3622,96.1512a8.33,8.33,0,0,0-8.33,8.33v5.9727a8.33,8.33,0,1,0,16.6607,0v-5.9727A8.33,8.33,0,0,0,95.3622,96.1512Z"
|
||||
/>
|
||||
<path
|
||||
class="cls-1"
|
||||
d="M166.8344,48.8968H65.6064A33.7544,33.7544,0,0,0,31.89,82.6131v57.07A33.7548,33.7548,0,0,0,65.6064,173.4h101.228a33.7549,33.7549,0,0,0,33.7168-33.7168v-57.07A33.7545,33.7545,0,0,0,166.8344,48.8968Zm2.831,90.4457a6.0733,6.0733,0,0,1-6.0732,6.0733H114.2168a43.5922,43.5922,0,0,0-21.3313,5.5757l-16.5647,9.2946v-14.87h-7.472a6.0733,6.0733,0,0,1-6.0733-6.0733v-60.5a6.0733,6.0733,0,0,1,6.0733-6.0733h94.7434a6.0733,6.0733,0,0,1,6.0732,6.0733Z"
|
||||
/>
|
||||
</svg>
|
||||
<img v-else src="@/assets/logo/logo.svg" :height="height" />
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import useStore from '@/stores'
|
||||
defineOptions({ name: 'LogoIcon' })
|
||||
|
||||
defineProps({
|
||||
height: {
|
||||
type: String,
|
||||
default: '36px'
|
||||
}
|
||||
})
|
||||
const { user } = useStore()
|
||||
const isDefaultTheme = computed(() => {
|
||||
return user.isDefaultTheme()
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.custom-logo-color {
|
||||
path {
|
||||
fill: var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -28,12 +28,6 @@
|
|||
<div class="value" v-else>{{ item.username }}</div>
|
||||
</template>
|
||||
</el-autocomplete>
|
||||
<!-- <el-input
|
||||
:validate-event="false"
|
||||
v-model="currentval"
|
||||
:placeholder="tagsList.length == 0 ? placeholder : ''"
|
||||
@keydown.enter="addTags"
|
||||
/> -->
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
<template>
|
||||
<div class="app-header" :class="!isDefaultTheme ? 'custom-header' : ''">
|
||||
<TopBar />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import TopBar from '../top-bar/index.vue'
|
||||
import useStore from '@/stores'
|
||||
const { user } = useStore()
|
||||
const isDefaultTheme = computed(() => {
|
||||
return user.isDefaultTheme()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.app-header {
|
||||
background: var(--app-header-bg-color);
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
}
|
||||
.custom-header {
|
||||
background: var(--el-color-primary-light-9) !important;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -36,7 +36,7 @@
|
|||
>
|
||||
<img src="@/assets/icon_web.svg" style="width: 58%" alt="" />
|
||||
</AppAvatar>
|
||||
<AppAvatar v-else class="mr-8" shape="square" :size="24">
|
||||
<AppAvatar v-else class="mr-8 avatar-blue" shape="square" :size="24">
|
||||
<img src="@/assets/icon_document.svg" style="width: 58%" alt="" />
|
||||
</AppAvatar>
|
||||
<div class="ellipsis">{{ current?.name }}</div>
|
||||
|
|
@ -228,7 +228,7 @@ onMounted(() => {
|
|||
border-radius: 4px;
|
||||
&:hover {
|
||||
background: var(--el-color-primary-light-9);
|
||||
color: var(--el-menu-active-color);
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
&__footer {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
export { default as Sidebar } from './sidebar/index.vue'
|
||||
export { default as AppMain } from './app-main/index.vue'
|
||||
export { default as TopBar } from './top-bar/index.vue'
|
||||
export { default as AppHeader } from './app-header/index.vue'
|
||||
|
|
|
|||
|
|
@ -50,6 +50,8 @@ const {
|
|||
params: { id, type }
|
||||
} = route as any
|
||||
|
||||
|
||||
|
||||
function showMenu() {
|
||||
if (isWorkFlow(type)) {
|
||||
return props.menu.name !== 'AppHitTest'
|
||||
|
|
@ -84,14 +86,14 @@ const menuIcon = computed(() => {
|
|||
border-radius: 4px;
|
||||
&:hover {
|
||||
background: none;
|
||||
color: var(--el-menu-active-color);
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
:deep(.el-sub-menu__title) {
|
||||
padding: 13px 12px 13px 16px !important;
|
||||
&:hover {
|
||||
background: none;
|
||||
color: var(--el-menu-active-color);
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
.el-sub-menu {
|
||||
|
|
@ -100,7 +102,7 @@ const menuIcon = computed(() => {
|
|||
}
|
||||
}
|
||||
.el-menu-item.is-active {
|
||||
color: var(--el-menu-active-color);
|
||||
color: var(--el-color-primary);
|
||||
background: var(--el-color-primary-light-9);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
<template>
|
||||
<el-dialog v-model="aboutDialogVisible" class="about-dialog border-r-4">
|
||||
<el-dialog
|
||||
v-model="aboutDialogVisible"
|
||||
class="about-dialog border-r-4"
|
||||
:class="!isDefaultTheme ? 'custom-header' : ''"
|
||||
>
|
||||
<template #header="{ titleId, titleClass }">
|
||||
<div class="logo flex-center" :id="titleId" :class="titleClass">
|
||||
<img src="@/assets/MaxKB-logo.svg" height="59" />
|
||||
<LogoFull height="59px" />
|
||||
</div>
|
||||
</template>
|
||||
<div class="about-ui">
|
||||
<el-card
|
||||
shadow="hover"
|
||||
class="mb-16"
|
||||
@click="toUrl('https://maxkb.cn/docs/')"
|
||||
>
|
||||
<el-card shadow="hover" class="mb-16" @click="toUrl('https://maxkb.cn/docs/')">
|
||||
<div class="flex align-center cursor">
|
||||
<AppIcon iconName="app-reading" class="mr-16 ml-8" style="font-size: 24px"></AppIcon>
|
||||
<span>{{ $t('layout.topbar.wiki') }}</span>
|
||||
|
|
@ -33,11 +33,12 @@
|
|||
</el-dialog>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { ref, computed } from 'vue'
|
||||
import useStore from '@/stores'
|
||||
const defaultTitle = import.meta.env.VITE_APP_TITLE
|
||||
|
||||
const { user } = useStore()
|
||||
const isDefaultTheme = computed(() => {
|
||||
return user.isDefaultTheme()
|
||||
})
|
||||
|
||||
const aboutDialogVisible = ref(false)
|
||||
|
||||
|
|
@ -80,4 +81,10 @@ defineExpose({ open })
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.custom-header {
|
||||
.el-dialog__header {
|
||||
background: var(--el-color-primary-light-9) !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
<div class="flex-center h-full">
|
||||
<div class="app-title-container cursor" @click="router.push('/')">
|
||||
<div class="logo flex-center">
|
||||
<img src="@/assets/MaxKB-logo.svg" height="35" />
|
||||
<LogoFull />
|
||||
</div>
|
||||
</div>
|
||||
<TopMenu></TopMenu>
|
||||
|
|
|
|||
|
|
@ -1,36 +1,15 @@
|
|||
<script setup lang="ts">
|
||||
import { TopBar, AppMain } from '../components'
|
||||
import { AppHeader, AppMain } from '../components'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="app-layout">
|
||||
<div class="app-header">
|
||||
<TopBar />
|
||||
</div>
|
||||
<AppHeader />
|
||||
<div class="app-main">
|
||||
<AppMain />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<style lang="scss">
|
||||
.app-layout {
|
||||
background-color: var(--app-layout-bg-color);
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.app-main {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
padding: var(--app-header-height) 0 0 !important;
|
||||
box-sizing: border-box;
|
||||
overflow: auto;
|
||||
}
|
||||
.app-header {
|
||||
background: var(--app-header-bg-color);
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
}
|
||||
@import './index.scss';
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -12,15 +12,7 @@
|
|||
<script setup lang="ts">
|
||||
import { Sidebar, AppMain } from '../components'
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.sidebar-container {
|
||||
box-sizing: border-box;
|
||||
transition: width 0.28s;
|
||||
width: var(--sidebar-width);
|
||||
min-width: var(--sidebar-width);
|
||||
background-color: var(--sidebar-bg-color);
|
||||
}
|
||||
.view-container {
|
||||
width: calc(100% - var(--sidebar-width));
|
||||
}
|
||||
<style lang="scss" scoped>
|
||||
@import './index.scss';
|
||||
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
<template>
|
||||
<div class="app-layout">
|
||||
<div class="app-header">
|
||||
<TopBar />
|
||||
</div>
|
||||
<AppHeader />
|
||||
<div class="app-main">
|
||||
<div class="main-layout h-full flex">
|
||||
<div class="sidebar-container">
|
||||
|
|
@ -17,37 +15,8 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { TopBar, Sidebar, AppMain } from '../components'
|
||||
import { AppHeader, Sidebar, AppMain } from '../components'
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.app-layout {
|
||||
background-color: var(--app-layout-bg-color);
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.app-main {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
padding: var(--app-header-height) 0 0 !important;
|
||||
box-sizing: border-box;
|
||||
overflow: auto;
|
||||
}
|
||||
.app-header {
|
||||
background: var(--app-header-bg-color);
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
}
|
||||
.sidebar-container {
|
||||
box-sizing: border-box;
|
||||
transition: width 0.28s;
|
||||
width: var(--sidebar-width);
|
||||
min-width: var(--sidebar-width);
|
||||
background-color: var(--sidebar-bg-color);
|
||||
}
|
||||
.view-container {
|
||||
width: calc(100% - var(--sidebar-width));
|
||||
}
|
||||
<style lang="scss" scoped>
|
||||
@import './index.scss';
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
.app-layout {
|
||||
background-color: var(--app-layout-bg-color);
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.app-main {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
padding: var(--app-header-height) 0 0 !important;
|
||||
box-sizing: border-box;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.sidebar-container {
|
||||
box-sizing: border-box;
|
||||
transition: width 0.28s;
|
||||
width: var(--sidebar-width);
|
||||
min-width: var(--sidebar-width);
|
||||
background-color: var(--sidebar-bg-color);
|
||||
}
|
||||
.view-container {
|
||||
width: calc(100% - var(--sidebar-width));
|
||||
}
|
||||
|
|
@ -4,7 +4,6 @@ import * as ElementPlusIcons from '@element-plus/icons-vue'
|
|||
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
|
||||
import { createApp } from 'vue'
|
||||
import { store } from '@/stores'
|
||||
import theme from '@/theme'
|
||||
import directives from '@/directives'
|
||||
import App from './App.vue'
|
||||
import router from '@/router'
|
||||
|
|
@ -56,8 +55,6 @@ app.use(ElementPlus, {
|
|||
locale: zhCn
|
||||
})
|
||||
|
||||
app.use(theme)
|
||||
|
||||
app.use(router)
|
||||
app.use(i18n)
|
||||
app.use(Components)
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { Role, ComplexPermission } from '@/utils/permission/type'
|
|||
const settingRouter = {
|
||||
path: '/setting',
|
||||
name: 'setting',
|
||||
meta: { icon: 'Setting', title: '系统设置', permission: 'SETTING:READ' },
|
||||
meta: { icon: 'Setting', title: '系统管理', permission: 'SETTING:READ' },
|
||||
redirect: () => {
|
||||
if (hasPermission(new Role('ADMIN'), 'AND')) {
|
||||
return '/user'
|
||||
|
|
@ -59,7 +59,7 @@ const settingRouter = {
|
|||
meta: {
|
||||
icon: 'app-setting',
|
||||
iconActive: 'app-setting-active',
|
||||
title: '系统设置',
|
||||
title: '系统管理',
|
||||
activeMenu: '/setting',
|
||||
parentPath: '/setting',
|
||||
parentName: 'setting',
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
import { defineStore } from 'pinia'
|
||||
import type { User } from '@/api/type/user'
|
||||
import UserApi from '@/api/user'
|
||||
import ThemeApi from '@/api/theme'
|
||||
import { useElementPlusTheme } from 'use-element-plus-theme'
|
||||
const { changeTheme } = useElementPlusTheme()
|
||||
|
||||
export interface userStateTypes {
|
||||
userType: number // 1 系统操作者 2 对话用户
|
||||
|
|
@ -10,6 +13,7 @@ export interface userStateTypes {
|
|||
accessToken?: string
|
||||
XPACK_LICENSE_IS_VALID: false
|
||||
isXPack: false
|
||||
themeInfo: any
|
||||
}
|
||||
|
||||
const useUserStore = defineStore({
|
||||
|
|
@ -20,9 +24,17 @@ const useUserStore = defineStore({
|
|||
token: '',
|
||||
version: '',
|
||||
XPACK_LICENSE_IS_VALID: false,
|
||||
isXPack: false
|
||||
isXPack: false,
|
||||
themeInfo: null
|
||||
}),
|
||||
actions: {
|
||||
isDefaultTheme() {
|
||||
return !this.themeInfo?.theme || this.themeInfo?.theme === '#3370FF'
|
||||
},
|
||||
setTheme(data: any) {
|
||||
changeTheme(data?.['theme'])
|
||||
this.themeInfo = data
|
||||
},
|
||||
isExpire() {
|
||||
return this.isXPack && !this.XPACK_LICENSE_IS_VALID
|
||||
},
|
||||
|
|
@ -78,6 +90,18 @@ const useUserStore = defineStore({
|
|||
})
|
||||
},
|
||||
|
||||
async theme() {
|
||||
return await ThemeApi.getThemeInfo().then((ok) => {
|
||||
this.themeInfo = ok.data
|
||||
changeTheme(this.themeInfo['theme'])
|
||||
window.document.title = this.themeInfo['title'] || 'MaxKB'
|
||||
const link = document.querySelector('link[rel="icon"]') as any
|
||||
if (link) {
|
||||
link['href'] = this.themeInfo['icon'] || '/favicon.ico'
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
async profile() {
|
||||
return UserApi.profile().then((ok) => {
|
||||
this.userInfo = ok.data
|
||||
|
|
|
|||
|
|
@ -369,8 +369,8 @@ h5 {
|
|||
|
||||
/* tag */
|
||||
.default-tag {
|
||||
background: var(--tag-default-bg);
|
||||
color: var(--tag-default-color);
|
||||
background: var(--el-color-primary-light-7);
|
||||
color: var(--el-color-primary);
|
||||
border: none;
|
||||
}
|
||||
.success-tag {
|
||||
|
|
@ -390,6 +390,12 @@ h5 {
|
|||
border-color: #e0d7f0;
|
||||
}
|
||||
|
||||
.blue-tag {
|
||||
background: #ebf1ff;
|
||||
color: #3370ff;
|
||||
border-color: #d6e2ff;
|
||||
}
|
||||
|
||||
/*
|
||||
card 无边框无阴影 灰色背景
|
||||
*/
|
||||
|
|
@ -455,6 +461,9 @@ h5 {
|
|||
.avatar-purple {
|
||||
background: #7f3bf5;
|
||||
}
|
||||
.avatar-blue {
|
||||
background: #3370ff;
|
||||
}
|
||||
|
||||
.success {
|
||||
color: var(--el-color-success);
|
||||
|
|
@ -651,3 +660,29 @@ h5 {
|
|||
border: 1px solid var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
.app-card {
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0px 2px 4px 0px rgba(31, 35, 41, 0.12);
|
||||
}
|
||||
|
||||
.app-radio-button-group {
|
||||
border: 1px solid var(--app-border-color-dark);
|
||||
border-radius: var(--el-border-radius-base);
|
||||
.el-radio-button {
|
||||
padding: 3px;
|
||||
}
|
||||
.el-radio-button__inner {
|
||||
border: none !important;
|
||||
border-radius: var(--el-border-radius-base) !important;
|
||||
padding: 5px 8px;
|
||||
font-weight: 400;
|
||||
}
|
||||
.el-radio-button__original-radio:checked + .el-radio-button__inner {
|
||||
color: var(--el-color-primary);
|
||||
background: var(--el-color-primary-light-9);
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
:root {
|
||||
--el-color-primary: #3370ff;
|
||||
--el-color-primary-light-9: rgba(51, 112, 255, 0.1);
|
||||
--el-color-primary: #3370FF;
|
||||
--el-menu-item-height: 45px;
|
||||
--el-box-shadow-light: 0px 2px 4px 0px rgba(31, 35, 41, 0.12);
|
||||
--el-border-color: #dee0e3;
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@
|
|||
--app-header-height: 56px;
|
||||
--app-header-padding: 0 20px;
|
||||
--app-header-bg-color: linear-gradient(90deg, #ebf1ff 24.34%, #e5fbf8 56.18%, #f2ebfe 90.18%);
|
||||
--app-logo-color: linear-gradient(180deg, #3370ff 0%, #7f3bf5 100%);
|
||||
--app-avatar-gradient-color: linear-gradient(270deg, #9258f7 0%, #3370ff 100%);
|
||||
--app-logo-color: linear-gradient(180deg, #3370FF 0%, #7f3bf5 100%);
|
||||
--app-avatar-gradient-color: linear-gradient(270deg, #9258f7 0%, #3370FF 100%);
|
||||
|
||||
/* 计算高度 */
|
||||
--app-main-height: calc(100vh - var(--app-header-height) - var(--app-view-padding) * 2 - 40px);
|
||||
|
|
|
|||
|
|
@ -1,13 +0,0 @@
|
|||
import type { InferData } from "./type";
|
||||
const inferData: Array<InferData> = [
|
||||
{
|
||||
key: "primary",
|
||||
value: "#3370FF",
|
||||
},
|
||||
{ key: "success", value: "#67c23a" },
|
||||
{ key: "warning", value: "#e6a23c" },
|
||||
{ key: "danger", value: "#f56c6c" },
|
||||
{ key: "error", value: "#F54A45" },
|
||||
{ key: "info", value: "#909399" },
|
||||
];
|
||||
export default inferData;
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
import type { KeyValueData } from './type'
|
||||
const keyValueData: KeyValueData = {
|
||||
'--el-header-padding': '0px'
|
||||
}
|
||||
export default keyValueData
|
||||
|
|
@ -1,281 +0,0 @@
|
|||
import type {
|
||||
ThemeSetting,
|
||||
InferData,
|
||||
KeyValueData,
|
||||
UpdateInferData,
|
||||
UpdateKeyValueData
|
||||
} from './type'
|
||||
import { TinyColor } from '@ctrl/tinycolor'
|
||||
// 引入默认推断数据
|
||||
import inferData from './defaultInferData'
|
||||
// 引入默认keyValue数据
|
||||
import keyValueData from './defaultKeyValueData'
|
||||
// 引入设置对象
|
||||
import setting from './setting'
|
||||
import type { App } from 'vue'
|
||||
declare global {
|
||||
interface ChildNode {
|
||||
innerText: string
|
||||
}
|
||||
}
|
||||
class Theme {
|
||||
/**
|
||||
* 主题设置
|
||||
*/
|
||||
themeSetting: ThemeSetting
|
||||
/**
|
||||
* 键值数据
|
||||
*/
|
||||
keyValue: KeyValueData
|
||||
/**
|
||||
* 外推数据
|
||||
*/
|
||||
inferData: Array<InferData>
|
||||
/**
|
||||
*是否是第一次初始化
|
||||
*/
|
||||
isFirstWriteStyle: boolean
|
||||
/**
|
||||
* 混色白
|
||||
*/
|
||||
colorWhite: string
|
||||
/**
|
||||
* 混色黑
|
||||
*/
|
||||
colorBlack: string
|
||||
|
||||
constructor(themeSetting: ThemeSetting, keyValue: KeyValueData, inferData: Array<InferData>) {
|
||||
this.themeSetting = themeSetting
|
||||
this.keyValue = keyValue
|
||||
this.inferData = inferData
|
||||
this.isFirstWriteStyle = true
|
||||
this.colorWhite = '#ffffff'
|
||||
this.colorBlack = '#000000'
|
||||
this.initDefaultTheme()
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼接
|
||||
* @param setting 主题设置
|
||||
* @param names 需要拼接的所有值
|
||||
* @returns 拼接后的数据
|
||||
*/
|
||||
getVarName = (setting: ThemeSetting, ...names: Array<string>) => {
|
||||
return (
|
||||
setting.startDivision + setting.namespace + setting.division + names.join(setting.division)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换外推数据
|
||||
* @param setting 主题设置对象
|
||||
* @param inferData 外推数据
|
||||
* @returns
|
||||
*/
|
||||
mapInferMainStyle = (setting: ThemeSetting, inferData: InferData) => {
|
||||
const key: string = this.getVarName(
|
||||
setting,
|
||||
inferData.setting ? inferData.setting.type : setting.colorInferSetting.type,
|
||||
inferData.key
|
||||
)
|
||||
return {
|
||||
[key]: inferData.value,
|
||||
...this.mapInferDataStyle(setting, inferData)
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 转换外推数据
|
||||
* @param setting 设置
|
||||
* @param inferData 外推数据
|
||||
*/
|
||||
mapInferData = (setting: ThemeSetting, inferData: Array<InferData>) => {
|
||||
return inferData
|
||||
.map((itemData) => {
|
||||
return this.mapInferMainStyle(setting, itemData)
|
||||
})
|
||||
.reduce((pre, next) => {
|
||||
return { ...pre, ...next }
|
||||
}, {})
|
||||
}
|
||||
/**
|
||||
* 转换外推数据
|
||||
* @param setting 主题设置对象
|
||||
* @param inferData 外推数据
|
||||
* @returns
|
||||
*/
|
||||
mapInferDataStyle = (setting: ThemeSetting, inferData: InferData) => {
|
||||
const inferSetting = inferData.setting ? inferData.setting : setting.colorInferSetting
|
||||
if (inferSetting.type === 'color') {
|
||||
return Object.keys(inferSetting)
|
||||
.map((key: string) => {
|
||||
if (key === 'light' || key === 'dark') {
|
||||
return inferSetting[key]
|
||||
.map((l: any) => {
|
||||
const varName = this.getVarName(
|
||||
setting,
|
||||
inferSetting.type,
|
||||
inferData.key,
|
||||
key,
|
||||
l.toString()
|
||||
)
|
||||
return {
|
||||
[varName]: new TinyColor(inferData.value)
|
||||
.mix(key === 'light' ? this.colorWhite : this.colorBlack, l * 10)
|
||||
.toHexString()
|
||||
}
|
||||
})
|
||||
.reduce((pre: any, next: any) => {
|
||||
return { ...pre, ...next }
|
||||
}, {})
|
||||
}
|
||||
return {}
|
||||
})
|
||||
.reduce((pre, next) => {
|
||||
return { ...pre, ...next }
|
||||
}, {})
|
||||
}
|
||||
return {}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param themeSetting 主题设置
|
||||
* @param keyValueData 键值数据
|
||||
* @returns 映射后的键值数据
|
||||
*/
|
||||
mapKeyValue = (themeSetting: ThemeSetting, keyValueData: KeyValueData) => {
|
||||
return Object.keys(keyValueData)
|
||||
.map((key: string) => {
|
||||
return {
|
||||
[this.updateKeyBySetting(key, themeSetting)]: keyValueData[key]
|
||||
}
|
||||
})
|
||||
.reduce((pre, next) => {
|
||||
return { ...pre, ...next }
|
||||
}, {})
|
||||
}
|
||||
/**
|
||||
* 根据配置文件修改Key
|
||||
* @param key key
|
||||
* @param themeSetting 主题设置
|
||||
* @returns
|
||||
*/
|
||||
updateKeyBySetting = (key: string, themeSetting: ThemeSetting) => {
|
||||
return key.startsWith(themeSetting.startDivision)
|
||||
? key
|
||||
: key.startsWith(themeSetting.namespace)
|
||||
? themeSetting.startDivision + key
|
||||
: key.startsWith(themeSetting.division)
|
||||
? themeSetting.startDivision + themeSetting.namespace
|
||||
: themeSetting.startDivision + themeSetting.namespace + themeSetting.division + key
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param setting 主题设置
|
||||
* @param keyValue 主题键值对数据
|
||||
* @param inferData 外推数据
|
||||
* @returns 合并后的键值对数据
|
||||
*/
|
||||
tokeyValueStyle = () => {
|
||||
return {
|
||||
...this.mapInferData(this.themeSetting, this.inferData),
|
||||
...this.mapKeyValue(this.themeSetting, this.keyValue)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将keyValue对象转换为S
|
||||
* @param keyValue
|
||||
* @returns
|
||||
*/
|
||||
toString = (keyValue: KeyValueData) => {
|
||||
const inner = Object.keys(keyValue)
|
||||
.map((key: string) => {
|
||||
return key + ':' + keyValue[key] + ';'
|
||||
})
|
||||
.join('')
|
||||
return `@charset "UTF-8";:root{${inner}}`
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param elNewStyle 新的变量样式
|
||||
*/
|
||||
writeNewStyle = (elNewStyle: string) => {
|
||||
if (this.isFirstWriteStyle) {
|
||||
const style = document.createElement('style')
|
||||
style.innerText = elNewStyle
|
||||
document.head.appendChild(style)
|
||||
this.isFirstWriteStyle = false
|
||||
} else {
|
||||
if (document.head.lastChild) {
|
||||
document.head.lastChild.innerText = elNewStyle
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改数据并且写入dom
|
||||
* @param updateInferData 平滑数据修改
|
||||
* @param updateKeyvalueData keyValue数据修改
|
||||
*/
|
||||
updateWrite = (updateInferData?: UpdateInferData, updateKeyvalueData?: UpdateKeyValueData) => {
|
||||
this.update(updateInferData, updateKeyvalueData)
|
||||
const newStyle = this.tokeyValueStyle()
|
||||
const newStyleString = this.toString(newStyle)
|
||||
this.writeNewStyle(newStyleString)
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改数据
|
||||
* @param inferData
|
||||
* @param keyvalueData
|
||||
*/
|
||||
update = (updateInferData?: UpdateInferData, updateKeyvalueData?: UpdateKeyValueData) => {
|
||||
if (updateInferData) {
|
||||
this.updateInferData(updateInferData)
|
||||
}
|
||||
if (updateKeyvalueData) {
|
||||
this.updateOrCreateKeyValueData(updateKeyvalueData)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改外推数据 外推数据只能修改,不能新增
|
||||
* @param inferData
|
||||
*/
|
||||
updateInferData = (updateInferData: UpdateInferData) => {
|
||||
Object.keys(updateInferData).forEach((key) => {
|
||||
const findInfer = this.inferData.find((itemInfer) => {
|
||||
return itemInfer.key === key
|
||||
})
|
||||
if (findInfer) {
|
||||
findInfer.value = updateInferData[key]
|
||||
} else {
|
||||
this.inferData.push({ key, value: updateInferData[key] })
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化默认主题
|
||||
*/
|
||||
initDefaultTheme = () => {
|
||||
this.updateWrite()
|
||||
}
|
||||
/**
|
||||
* 修改KeyValue数据
|
||||
* @param keyvalueData keyValue数据
|
||||
*/
|
||||
updateOrCreateKeyValueData = (updateKeyvalueData: UpdateKeyValueData) => {
|
||||
Object.keys(updateKeyvalueData).forEach((key) => {
|
||||
const newKey = this.updateKeyBySetting(key, this.themeSetting)
|
||||
this.keyValue[newKey] = updateKeyvalueData[newKey]
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const install = (app: App) => {
|
||||
app.config.globalProperties.theme = new Theme(setting, keyValueData, inferData)
|
||||
}
|
||||
export default { install }
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
import type { ThemeSetting } from "./type";
|
||||
const setting: ThemeSetting = {
|
||||
namespace: "el",
|
||||
division: "-",
|
||||
startDivision: "--",
|
||||
colorInferSetting: {
|
||||
light: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
|
||||
dark: [2],
|
||||
type: "color",
|
||||
},
|
||||
};
|
||||
export default setting;
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
interface ThemeSetting {
|
||||
/**
|
||||
*element-ui Namespace
|
||||
*/
|
||||
namespace: string;
|
||||
/**
|
||||
* 数据分隔符
|
||||
*/
|
||||
division: string;
|
||||
/**
|
||||
* 前缀
|
||||
*/
|
||||
startDivision: string;
|
||||
/**
|
||||
* 颜色外推设置
|
||||
*/
|
||||
colorInferSetting: ColorInferSetting;
|
||||
}
|
||||
|
||||
/**
|
||||
* 颜色混和设置
|
||||
*/
|
||||
interface ColorInferSetting {
|
||||
/**
|
||||
* 与白色混
|
||||
*/
|
||||
light: Array<number>;
|
||||
/**
|
||||
* 与黑色混
|
||||
*/
|
||||
dark: Array<number>;
|
||||
/**
|
||||
* 类型
|
||||
*/
|
||||
type: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 平滑数据
|
||||
*/
|
||||
interface KeyValueData {
|
||||
[propName: string]: string;
|
||||
}
|
||||
type UpdateInferData = KeyValueData;
|
||||
|
||||
type UpdateKeyValueData = KeyValueData;
|
||||
/**
|
||||
*平滑数据
|
||||
*/
|
||||
interface InferData {
|
||||
/**
|
||||
* 设置
|
||||
*/
|
||||
setting?: ColorInferSetting | any;
|
||||
/**
|
||||
* 健
|
||||
*/
|
||||
key: string;
|
||||
/**
|
||||
* 值
|
||||
*/
|
||||
value: string;
|
||||
}
|
||||
|
||||
export type {
|
||||
KeyValueData,
|
||||
InferData,
|
||||
ThemeSetting,
|
||||
UpdateInferData,
|
||||
UpdateKeyValueData,
|
||||
};
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
export const themeList = [
|
||||
{
|
||||
label: '默认',
|
||||
value: '#3370FF',
|
||||
loginBackground: 'default'
|
||||
},
|
||||
{
|
||||
label: '活力橙',
|
||||
value: '#FF8800',
|
||||
loginBackground: 'orange'
|
||||
},
|
||||
{
|
||||
label: '松石绿',
|
||||
value: '#00B69D',
|
||||
loginBackground: 'green'
|
||||
},
|
||||
{
|
||||
label: '商务蓝',
|
||||
value: '#4954E6',
|
||||
loginBackground: 'default'
|
||||
},
|
||||
{
|
||||
label: '神秘紫',
|
||||
value: '#7F3BF5',
|
||||
loginBackground: 'purple'
|
||||
},
|
||||
{
|
||||
label: '胭脂红',
|
||||
value: '#F01D94',
|
||||
loginBackground: 'red'
|
||||
}
|
||||
]
|
||||
|
||||
export function getThemeImg(val: string) {
|
||||
return themeList.filter((v) => v.value === val)?.[0]?.loginBackground || 'default'
|
||||
}
|
||||
|
||||
export const defaultSetting = {
|
||||
icon: '',
|
||||
loginLogo: '',
|
||||
loginImage: '',
|
||||
title: 'MaxKB',
|
||||
slogan: '欢迎使用 MaxKB 智能知识库'
|
||||
}
|
||||
|
|
@ -64,7 +64,7 @@
|
|||
<div class="mr-16">
|
||||
<el-button link @click="enlarge = !enlarge">
|
||||
<AppIcon
|
||||
:iconName="enlarge ? 'app-magnify' : 'app-minify'"
|
||||
:iconName="enlarge ? 'app-minify' : 'app-magnify'"
|
||||
class="color-secondary"
|
||||
style="font-size: 20px"
|
||||
></AppIcon>
|
||||
|
|
|
|||
|
|
@ -220,7 +220,7 @@
|
|||
<img src="@/assets/icon_web.svg" style="width: 58%" alt="" />
|
||||
</AppAvatar>
|
||||
|
||||
<AppAvatar v-else class="mr-8" shape="square" :size="32">
|
||||
<AppAvatar v-else class="mr-8 avatar-blue" shape="square" :size="32">
|
||||
<img src="@/assets/icon_document.svg" style="width: 58%" alt="" />
|
||||
</AppAvatar>
|
||||
<div class="ellipsis">
|
||||
|
|
|
|||
|
|
@ -218,7 +218,7 @@
|
|||
<img src="@/assets/icon_web.svg" style="width: 58%" alt="" />
|
||||
</AppAvatar>
|
||||
|
||||
<AppAvatar v-else class="mr-8" shape="square" :size="32">
|
||||
<AppAvatar v-else class="mr-8 avatar-blue" shape="square" :size="32">
|
||||
<img src="@/assets/icon_document.svg" style="width: 58%" alt="" />
|
||||
</AppAvatar>
|
||||
<div class="ellipsis">
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@
|
|||
</template>
|
||||
<div class="status-tag">
|
||||
<el-tag type="warning" v-if="isWorkFlow(item.type)">高级编排</el-tag>
|
||||
<el-tag v-else>简单配置</el-tag>
|
||||
<el-tag class="blue-tag" v-else>简单配置</el-tag>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div class="authentication-setting p-24">
|
||||
<h4>{{$t('login.authentication')}}</h4>
|
||||
<h4>{{ $t('login.authentication') }}</h4>
|
||||
<el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
|
||||
<template v-for="(item, index) in tabList" :key="index">
|
||||
<el-tab-pane :label="item.label" :name="item.name">
|
||||
|
|
@ -29,13 +29,6 @@ const tabList = [
|
|||
}
|
||||
]
|
||||
|
||||
// 动态引入组件
|
||||
const loadComponent = async (componentName: string) => {
|
||||
await import(`./component/${componentName}.vue`).then((res) => res.default)
|
||||
}
|
||||
|
||||
const currentComponent = computed(() => loadComponent(activeName.value))
|
||||
|
||||
function handleClick() {}
|
||||
|
||||
onMounted(() => {})
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
<el-form-item label="知识库类型" required>
|
||||
<el-card shadow="never" class="mb-8" v-if="detail.type === '0'">
|
||||
<div class="flex align-center">
|
||||
<AppAvatar class="mr-8" shape="square" :size="32">
|
||||
<AppAvatar class="mr-8 avatar-blue" shape="square" :size="32">
|
||||
<img src="@/assets/icon_document.svg" style="width: 58%" alt="" />
|
||||
</AppAvatar>
|
||||
<div>
|
||||
|
|
|
|||
|
|
@ -41,12 +41,12 @@
|
|||
>
|
||||
<img src="@/assets/icon_web.svg" style="width: 58%" alt="" />
|
||||
</AppAvatar>
|
||||
<AppAvatar v-else class="mr-8" shape="square" :size="32">
|
||||
<AppAvatar v-else class="mr-8 avatar-blue" shape="square" :size="32">
|
||||
<img src="@/assets/icon_document.svg" style="width: 58%" alt="" />
|
||||
</AppAvatar>
|
||||
</template>
|
||||
<div class="delete-button">
|
||||
<el-tag v-if="item.type === '0'">通用型</el-tag>
|
||||
<el-tag class="blue-tag" v-if="item.type === '0'">通用型</el-tag>
|
||||
<el-tag class="purple-tag" v-else-if="item.type === '1'" type="warning"
|
||||
>Web 站点</el-tag
|
||||
>
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
<el-card shadow="never" class="mb-16" :class="form.type === '0' ? 'active' : ''">
|
||||
<el-radio value="0" size="large">
|
||||
<div class="flex align-center">
|
||||
<AppAvatar class="mr-8" shape="square" :size="32">
|
||||
<AppAvatar class="mr-8 avatar-blue" shape="square" :size="32">
|
||||
<img src="@/assets/icon_document.svg" style="width: 58%" alt="" />
|
||||
</AppAvatar>
|
||||
<div>
|
||||
|
|
|
|||
|
|
@ -21,7 +21,12 @@
|
|||
>
|
||||
<el-radio :value="item.id" size="large">
|
||||
<div class="flex align-center">
|
||||
<AppAvatar v-if="item?.type === '0'" class="mr-8" shape="square" :size="32">
|
||||
<AppAvatar
|
||||
v-if="item?.type === '0'"
|
||||
class="mr-8 avatar-blue"
|
||||
shape="square"
|
||||
:size="32"
|
||||
>
|
||||
<img src="@/assets/icon_document.svg" style="width: 58%" alt="" />
|
||||
</AppAvatar>
|
||||
<AppAvatar
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@
|
|||
</AppAvatar>
|
||||
<AppAvatar
|
||||
v-else-if="!item.dataset_id && item.type === '0'"
|
||||
class="mr-12"
|
||||
class="mr-12 avatar-blue"
|
||||
shape="square"
|
||||
:size="24"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -1,21 +1,21 @@
|
|||
<template>
|
||||
<login-layout v-loading="loading">
|
||||
<LoginContainer subTitle="欢迎使用 MaxKB 智能知识库">
|
||||
<LoginContainer :subTitle="user.themeInfo?.slogan || '欢迎使用 MaxKB 智能知识库'">
|
||||
<h2 class="mb-24">{{ loginMode || '普通登录' }}</h2>
|
||||
<el-form
|
||||
class="login-form"
|
||||
:rules="rules"
|
||||
:model="loginForm"
|
||||
ref="loginFormRef"
|
||||
@keyup.enter="login"
|
||||
class="login-form"
|
||||
:rules="rules"
|
||||
:model="loginForm"
|
||||
ref="loginFormRef"
|
||||
@keyup.enter="login"
|
||||
>
|
||||
<div class="mb-24">
|
||||
<el-form-item prop="username">
|
||||
<el-input
|
||||
size="large"
|
||||
class="input-item"
|
||||
v-model="loginForm.username"
|
||||
placeholder="请输入用户名"
|
||||
size="large"
|
||||
class="input-item"
|
||||
v-model="loginForm.username"
|
||||
placeholder="请输入用户名"
|
||||
>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
|
|
@ -23,12 +23,12 @@
|
|||
<div class="mb-24">
|
||||
<el-form-item prop="password">
|
||||
<el-input
|
||||
type="password"
|
||||
size="large"
|
||||
class="input-item"
|
||||
v-model="loginForm.password"
|
||||
placeholder="请输入密码"
|
||||
show-password
|
||||
type="password"
|
||||
size="large"
|
||||
class="input-item"
|
||||
v-model="loginForm.password"
|
||||
placeholder="请输入密码"
|
||||
show-password
|
||||
>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
|
|
@ -40,10 +40,10 @@
|
|||
注册
|
||||
</el-button> -->
|
||||
<el-button
|
||||
class="forgot-password"
|
||||
@click="router.push('/forgot_password')"
|
||||
link
|
||||
type="primary"
|
||||
class="forgot-password"
|
||||
@click="router.push('/forgot_password')"
|
||||
link
|
||||
type="primary"
|
||||
>
|
||||
忘记密码?
|
||||
</el-button>
|
||||
|
|
@ -55,21 +55,21 @@
|
|||
<div class="text-center mt-16">
|
||||
<template v-for="item in modeList">
|
||||
<el-button
|
||||
v-if="item !== ''&&loginMode !== item"
|
||||
circle
|
||||
:key="item"
|
||||
class="login-button-circle color-secondary"
|
||||
@click="changeMode(item)"
|
||||
>{{ item }}
|
||||
v-if="item !== '' && loginMode !== item"
|
||||
circle
|
||||
:key="item"
|
||||
class="login-button-circle color-secondary"
|
||||
@click="changeMode(item)"
|
||||
>{{ item }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="item === ''&&loginMode !== ''"
|
||||
circle
|
||||
:key="item"
|
||||
class="login-button-circle color-secondary"
|
||||
style="font-size: 24px"
|
||||
icon="UserFilled"
|
||||
@click="changeMode('')"
|
||||
v-if="item === '' && loginMode !== ''"
|
||||
circle
|
||||
:key="item"
|
||||
class="login-button-circle color-secondary"
|
||||
style="font-size: 24px"
|
||||
icon="UserFilled"
|
||||
@click="changeMode('')"
|
||||
/>
|
||||
</template>
|
||||
</div>
|
||||
|
|
@ -77,14 +77,14 @@
|
|||
</login-layout>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import {onMounted, ref} from 'vue'
|
||||
import type {LoginRequest} from '@/api/type/user'
|
||||
import {useRouter} from 'vue-router'
|
||||
import type {FormInstance, FormRules} from 'element-plus'
|
||||
import { onMounted, ref } from 'vue'
|
||||
import type { LoginRequest } from '@/api/type/user'
|
||||
import { useRouter } from 'vue-router'
|
||||
import type { FormInstance, FormRules } from 'element-plus'
|
||||
import useStore from '@/stores'
|
||||
|
||||
const loading = ref<boolean>(false)
|
||||
const {user} = useStore()
|
||||
const { user } = useStore()
|
||||
const router = useRouter()
|
||||
const loginForm = ref<LoginRequest>({
|
||||
username: '',
|
||||
|
|
@ -109,8 +109,7 @@ const rules = ref<FormRules<LoginRequest>>({
|
|||
})
|
||||
const loginFormRef = ref<FormInstance>()
|
||||
|
||||
|
||||
const modeList = ref<string[]>(['']);
|
||||
const modeList = ref<string[]>([''])
|
||||
const loginMode = ref('')
|
||||
|
||||
function changeMode(val: string) {
|
||||
|
|
@ -126,25 +125,28 @@ const login = () => {
|
|||
loginFormRef.value?.validate().then(() => {
|
||||
loading.value = true
|
||||
user
|
||||
.login(loginMode.value, loginForm.value.username, loginForm.value.password)
|
||||
.then(() => {
|
||||
router.push({name: 'home'})
|
||||
})
|
||||
.finally(() => (loading.value = false))
|
||||
.login(loginMode.value, loginForm.value.username, loginForm.value.password)
|
||||
.then(() => {
|
||||
router.push({ name: 'home' })
|
||||
})
|
||||
.finally(() => (loading.value = false))
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
user.theme()
|
||||
user.asyncGetProfile().then((res) => {
|
||||
if (user.isXPack) {
|
||||
loading.value = true
|
||||
user.getAuthType().then((res) => {
|
||||
modeList.value = [...modeList.value, ...res];
|
||||
}).finally(() => (loading.value = false))
|
||||
user
|
||||
.getAuthType()
|
||||
.then((res) => {
|
||||
modeList.value = [...modeList.value, ...res]
|
||||
})
|
||||
.finally(() => (loading.value = false))
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
</script>
|
||||
<style lang="scss" scope>
|
||||
.login-gradient-divider {
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
</AppAvatar>
|
||||
<AppAvatar
|
||||
v-else-if="!item.dataset_id && item.type === '0'"
|
||||
class="mr-12"
|
||||
class="mr-12 avatar-blue"
|
||||
shape="square"
|
||||
:size="24"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -22,27 +22,6 @@
|
|||
>
|
||||
<el-form-item label="用户名/邮箱" prop="users">
|
||||
<tags-input v-model:tags="memberForm.users" placeholder="请输入成员的用户名或邮箱" />
|
||||
<!-- <el-select
|
||||
ref="SelectRemoteRef"
|
||||
class="custom-select-multiple"
|
||||
v-model="memberForm.users"
|
||||
multiple
|
||||
filterable
|
||||
remote
|
||||
reserve-keyword
|
||||
placeholder="请输入成员的用户名或邮箱"
|
||||
no-data-text="用户不存在"
|
||||
:remote-method="remoteMethod"
|
||||
:loading="loading"
|
||||
@change="changeSelectHandle"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in userOptions"
|
||||
:key="item?.id"
|
||||
:label="item?.username"
|
||||
:value="item?.id"
|
||||
/>
|
||||
</el-select> -->
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
shape="square"
|
||||
:size="24"
|
||||
/>
|
||||
<AppAvatar v-else-if="isDataset" class="mr-12" shape="square" :size="24">
|
||||
<AppAvatar v-else-if="isDataset" class="mr-12 avatar-blue" shape="square" :size="24">
|
||||
<img src="@/assets/icon_document.svg" style="width: 58%" alt="" />
|
||||
</AppAvatar>
|
||||
<auto-tooltip :content="row?.name">
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
<el-progress
|
||||
type="circle"
|
||||
:width="56"
|
||||
color="#3370ff"
|
||||
color="#3370FF"
|
||||
:percentage="progress"
|
||||
class="percentage"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,104 @@
|
|||
<template>
|
||||
<div class="login-preview mr-16">
|
||||
<div class="header">
|
||||
<div class="tag flex-between">
|
||||
<div class="flex align-center">
|
||||
<img v-if="props.data.icon" :src="fileURL" alt="" height="20px" class="mr-8" />
|
||||
<img v-else src="@/assets/logo/logo.svg" height="24px" class="mr-8" />
|
||||
<span class="ellipsis">{{ data.title }}</span>
|
||||
</div>
|
||||
<el-icon><Close /></el-icon>
|
||||
</div>
|
||||
</div>
|
||||
<login-layout style="height: 530px">
|
||||
<LoginContainer :subTitle="data.slogan" class="login-container">
|
||||
<div class="mask"></div>
|
||||
<h2 class="mb-24">{{ '普通登录' }}</h2>
|
||||
<el-form class="login-form">
|
||||
<div class="mb-24">
|
||||
<el-form-item>
|
||||
<el-input size="large" class="input-item" placeholder="请输入用户名"> </el-input>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="mb-24">
|
||||
<el-form-item>
|
||||
<el-input
|
||||
type="password"
|
||||
size="large"
|
||||
class="input-item"
|
||||
placeholder="请输入密码"
|
||||
show-password
|
||||
>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form>
|
||||
<el-button size="large" type="primary" class="w-full">登录</el-button>
|
||||
<div class="operate-container flex-between mt-12">
|
||||
<el-button class="forgot-password" link type="primary"> 忘记密码? </el-button>
|
||||
</div>
|
||||
</LoginContainer>
|
||||
</login-layout>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
default: null
|
||||
}
|
||||
})
|
||||
|
||||
const fileURL = computed(() => {
|
||||
if (props.data.icon) {
|
||||
if (typeof props.data.icon === 'string') {
|
||||
return props.data.icon
|
||||
} else {
|
||||
return URL.createObjectURL(props.data.icon)
|
||||
}
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.login-preview {
|
||||
background: #ffffff;
|
||||
border-radius: 4px;
|
||||
transform-origin: center;
|
||||
.login-container {
|
||||
transform: translate(0, 0) scale(0.8);
|
||||
position: relative;
|
||||
.mask {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
z-index: 3;
|
||||
}
|
||||
}
|
||||
|
||||
.header {
|
||||
background: #eff0f1;
|
||||
height: 38px;
|
||||
border-radius: 4px 4px 0 0;
|
||||
position: relative;
|
||||
.tag {
|
||||
width: 180px;
|
||||
height: 30px;
|
||||
background: #ffffff;
|
||||
box-shadow: var(-app-text-color-light-1);
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 8px;
|
||||
border-radius: 4px 4px 0 0;
|
||||
padding: 0 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,5 +1,255 @@
|
|||
<template>
|
||||
<LayoutContainer header="外观设置"> </LayoutContainer>
|
||||
<div class="theme-setting" v-loading="loading">
|
||||
<h4 class="p-16-24">外观设置</h4>
|
||||
<el-scrollbar>
|
||||
<div class="p-24 pt-0">
|
||||
<div class="app-card p-24">
|
||||
<h5 class="mb-16">平台显示主题</h5>
|
||||
<el-radio-group
|
||||
v-model="themeForm.theme"
|
||||
class="app-radio-button-group"
|
||||
@change="changeThemeHandle"
|
||||
>
|
||||
<template v-for="(item, index) in themeList" :key="index">
|
||||
<el-radio-button :label="item.label" :value="item.value" />
|
||||
</template>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<div class="app-card p-24 mt-16">
|
||||
<h5 class="mb-16">平台登陆设置</h5>
|
||||
<el-card shadow="never" class="layout-bg">
|
||||
<div class="flex-between">
|
||||
<h5 class="mb-16">页面预览</h5>
|
||||
<el-button type="primary" link @click="resetForm"> 恢复默认 </el-button>
|
||||
</div>
|
||||
<div class="theme-preview">
|
||||
<el-row :gutter="8">
|
||||
<el-col :span="16">
|
||||
<LoginPreview :data="themeForm" />
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<div class="theme-form">
|
||||
<el-card shadow="never" class="mb-8">
|
||||
<div class="flex-between mb-8">
|
||||
<span class="lighter">网站 Logo</span>
|
||||
<el-upload
|
||||
ref="uploadRef"
|
||||
action="#"
|
||||
:auto-upload="false"
|
||||
:show-file-list="false"
|
||||
accept="image/*"
|
||||
:on-change="
|
||||
(file: any, fileList: any) => onChange(file, fileList, 'icon')
|
||||
"
|
||||
>
|
||||
<el-button size="small"> 替换图片 </el-button>
|
||||
</el-upload>
|
||||
</div>
|
||||
<el-text type="info" size="small"
|
||||
>顶部网站显示的 Logo,建议尺寸 48 x 48,支持 JPG、PNG、SVG,大小不超过
|
||||
200KB</el-text
|
||||
>
|
||||
</el-card>
|
||||
<el-card shadow="never" class="mb-8">
|
||||
<div class="flex-between mb-8">
|
||||
<span class="lighter">登录 Logo</span>
|
||||
<el-upload
|
||||
ref="uploadRef"
|
||||
action="#"
|
||||
:auto-upload="false"
|
||||
:show-file-list="false"
|
||||
accept="image/*"
|
||||
:on-change="
|
||||
(file: any, fileList: any) => onChange(file, fileList, 'loginLogo')
|
||||
"
|
||||
>
|
||||
<el-button size="small"> 替换图片 </el-button>
|
||||
</el-upload>
|
||||
</div>
|
||||
<el-text type="info" size="small"
|
||||
>登录页面右侧 Logo,建议尺寸 204*52,支持 JPG、PNG、SVG,大小不超过
|
||||
200KB</el-text
|
||||
>
|
||||
</el-card>
|
||||
<el-card shadow="never" class="mb-8">
|
||||
<div class="flex-between mb-8">
|
||||
<span class="lighter">登录背景图</span>
|
||||
<el-upload
|
||||
ref="uploadRef"
|
||||
action="#"
|
||||
:auto-upload="false"
|
||||
:show-file-list="false"
|
||||
accept="image/*"
|
||||
:on-change="
|
||||
(file: any, fileList: any) => onChange(file, fileList, 'loginImage')
|
||||
"
|
||||
>
|
||||
<el-button size="small"> 替换图片 </el-button>
|
||||
</el-upload>
|
||||
</div>
|
||||
<el-text type="info" size="small">
|
||||
左侧背景图,矢量图建议尺寸 576*900,位图建议尺寸1152*1800;支持
|
||||
JPG、PNG、SVG,大小不超过 5M
|
||||
</el-text>
|
||||
</el-card>
|
||||
|
||||
<el-form
|
||||
ref="themeFormRef"
|
||||
:model="themeForm"
|
||||
label-position="top"
|
||||
require-asterisk-position="right"
|
||||
:rules="rules"
|
||||
@submit.prevent
|
||||
>
|
||||
<el-form-item label="网站名称" prop="title">
|
||||
<el-input v-model="themeForm.title" placeholder="请输入网站名称">
|
||||
</el-input>
|
||||
<el-text type="info"> 显示在网页 Tab 的平台名称 </el-text>
|
||||
</el-form-item>
|
||||
<el-form-item label="欢迎语" prop="slogan">
|
||||
<el-input v-model="themeForm.slogan" placeholder="请输入欢迎语"> </el-input>
|
||||
<el-text type="info"> 产品 Logo 下的 欢迎语 </el-text>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div></el-col
|
||||
>
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
<div class="mt-16">
|
||||
<el-text type="info">默认为 MaxKB 登录界面,支持自定义设置</el-text>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
<div class="theme-setting__operate w-full p-16-24">
|
||||
<el-button @click="resetTheme">放弃更新</el-button>
|
||||
<el-button type="primary" @click="updataTheme(themeFormRef)"> 保存并应用 </el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts"></script>
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, onMounted, computed, watch } from 'vue'
|
||||
import { onBeforeRouteLeave } from 'vue-router'
|
||||
import type { FormInstance, FormRules, UploadFiles } from 'element-plus'
|
||||
import { cloneDeep } from 'lodash'
|
||||
import LoginPreview from './LoginPreview.vue'
|
||||
import { themeList, defaultSetting } from '@/utils/theme'
|
||||
import ThemeApi from '@/api/theme'
|
||||
import { MsgSuccess, MsgError } from '@/utils/message'
|
||||
import useStore from '@/stores'
|
||||
|
||||
const { user } = useStore()
|
||||
|
||||
onBeforeRouteLeave((to, from) => {
|
||||
user.setTheme(cloneTheme.value)
|
||||
})
|
||||
|
||||
const themeInfo = computed(() => user.themeInfo)
|
||||
|
||||
const themeFormRef = ref<FormInstance>()
|
||||
const loading = ref(false)
|
||||
const cloneTheme = ref(null)
|
||||
const themeForm = ref<any>({
|
||||
theme: '#3370FF',
|
||||
icon: '',
|
||||
loginLogo: '',
|
||||
loginImage: '',
|
||||
title: 'MaxKB',
|
||||
slogan: '欢迎使用 MaxKB 智能知识库'
|
||||
})
|
||||
|
||||
const rules = reactive<FormRules>({
|
||||
title: [{ required: true, message: '请输入网站标题', trigger: 'blur' }],
|
||||
slogan: [{ required: true, message: '请输入欢迎语', trigger: 'blur' }]
|
||||
})
|
||||
|
||||
const onChange = (file: any, fileList: UploadFiles, attr: string) => {
|
||||
if (attr === 'loginImage') {
|
||||
const isLimit = file?.size / 1024 / 1024 < 5
|
||||
if (!isLimit) {
|
||||
// @ts-ignore
|
||||
MsgError(`文件大小超过 5M`)
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
const isLimit = file?.size / 1024 < 200
|
||||
if (!isLimit) {
|
||||
// @ts-ignore
|
||||
MsgError(`文件大小超过 200KB`)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
themeForm.value[attr] = file.raw
|
||||
}
|
||||
|
||||
function changeThemeHandle(val: string) {
|
||||
themeForm.value.theme = val
|
||||
user.setTheme(themeForm.value)
|
||||
}
|
||||
|
||||
function resetTheme() {
|
||||
user.setTheme(cloneTheme.value)
|
||||
themeForm.value = cloneDeep(themeInfo.value)
|
||||
}
|
||||
|
||||
function resetForm() {
|
||||
themeForm.value = {
|
||||
theme: themeForm.value.theme,
|
||||
...defaultSetting
|
||||
}
|
||||
user.setTheme(themeForm.value)
|
||||
}
|
||||
|
||||
const updataTheme = async (formEl: FormInstance | undefined, test?: string) => {
|
||||
if (!formEl) return
|
||||
await formEl.validate((valid, fields) => {
|
||||
if (valid) {
|
||||
let fd = new FormData()
|
||||
Object.keys(themeForm.value).map((item) => {
|
||||
fd.append(item, themeForm.value[item])
|
||||
})
|
||||
ThemeApi.postThemeInfo(fd, loading).then((res) => {
|
||||
user.theme()
|
||||
cloneTheme.value = cloneDeep(themeForm.value)
|
||||
MsgSuccess('外观设置成功')
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (themeInfo.value) {
|
||||
themeForm.value = themeInfo.value
|
||||
cloneTheme.value = cloneDeep(themeInfo.value)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.theme-setting {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
padding-bottom: 64px;
|
||||
|
||||
&__operate {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
background: #ffffff;
|
||||
text-align: right;
|
||||
box-sizing: border-box;
|
||||
box-shadow: 0px -2px 4px 0px rgba(31, 35, 41, 0.08);
|
||||
}
|
||||
.theme-preview {
|
||||
min-width: 1000px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div @mousedown="mousedown" class="workflow-node-container p-16" style="overflow: visible">
|
||||
<div
|
||||
class="step-container p-16"
|
||||
class="step-container app-card p-16"
|
||||
:class="props.nodeModel.isSelected ? 'isSelected' : ''"
|
||||
style="overflow: visible"
|
||||
>
|
||||
|
|
@ -161,14 +161,8 @@ function showOperate(type: string) {
|
|||
<style lang="scss" scoped>
|
||||
.workflow-node-container {
|
||||
.step-container {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
border-radius: 9px;
|
||||
border: 2px solid #ffffff !important;
|
||||
box-shadow: 0px 2px 4px 0px rgba(31, 35, 41, 0.12);
|
||||
box-sizing: border-box;
|
||||
&:hover {
|
||||
box-shadow: 0px 6px 24px 0px rgba(31, 35, 41, 0.08);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<AppAvatar shape="square">
|
||||
<AppAvatar shape="square" class="avatar-blue">
|
||||
<img src="@/assets/icon_document.svg" style="width: 58%" alt="" />
|
||||
</AppAvatar>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@
|
|||
<img src="@/assets/icon_web.svg" style="width: 58%" alt="" />
|
||||
</AppAvatar>
|
||||
|
||||
<AppAvatar v-else class="mr-8" shape="square" :size="20">
|
||||
<AppAvatar v-else class="mr-8 avatar-blue" shape="square" :size="20">
|
||||
<img src="@/assets/icon_document.svg" style="width: 58%" alt="" />
|
||||
</AppAvatar>
|
||||
<div class="ellipsis">
|
||||
|
|
|
|||