基本功能实现!还有挺多BUG
BIN
images/SwiftUI.png
Normal file
After Width: | Height: | Size: 2 KiB |
BIN
images/g.jpeg
Normal file
After Width: | Height: | Size: 88 KiB |
BIN
images/icon.png
Normal file
After Width: | Height: | Size: 5.3 KiB |
1
images/icon.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<svg height="1024" width="1024" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" x="0px" y="0px" viewBox="0 0 100 100"><g><path d="M78.846,43.805c0.226-11.807-9.155-22.283-20.687-22.283c-7.107,0-13.433,3.484-17.563,8.91 c-4.529-5.971-22.354-1.723-19.441,13.373C12.919,45.133,5,51.297,5,60.367c0,10.002,7.676,18.111,17.145,18.111H44V60.502H32 l18-18.01l18,18.01H56v17.977h21.855C87.324,78.479,95,70.369,95,60.367C95,51.32,87.418,43.717,78.846,43.805z"></path></g></svg>
|
After Width: | Height: | Size: 511 B |
BIN
images/lol.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
images/pic_list.png
Normal file
After Width: | Height: | Size: 7.2 KiB |
BIN
images/setting.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
images/setting_icon.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
361
images/todo.svg
Normal file
|
@ -0,0 +1,361 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="120"
|
||||||
|
height="120"
|
||||||
|
viewBox="0 0 120 120"
|
||||||
|
version="1.1"
|
||||||
|
id="svg5"
|
||||||
|
sodipodi:docname="新建文档 1.2022_01_22_12_01_40.0.svg"
|
||||||
|
inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20, custom)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview7"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
showgrid="true"
|
||||||
|
inkscape:zoom="4.531376"
|
||||||
|
inkscape:cx="68.30155"
|
||||||
|
inkscape:cy="50.426184"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1015"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="layer1">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid9" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<defs
|
||||||
|
id="defs2">
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="bspline"
|
||||||
|
id="path-effect2507"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
weight="33.333333"
|
||||||
|
steps="2"
|
||||||
|
helper_size="0"
|
||||||
|
apply_no_weight="true"
|
||||||
|
apply_with_weight="true"
|
||||||
|
only_selected="false" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="bspline"
|
||||||
|
id="path-effect952"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
weight="33.333333"
|
||||||
|
steps="2"
|
||||||
|
helper_size="0"
|
||||||
|
apply_no_weight="true"
|
||||||
|
apply_with_weight="true"
|
||||||
|
only_selected="false" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="bspline"
|
||||||
|
id="path-effect948"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
weight="33.333333"
|
||||||
|
steps="2"
|
||||||
|
helper_size="0"
|
||||||
|
apply_no_weight="true"
|
||||||
|
apply_with_weight="true"
|
||||||
|
only_selected="false" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="bspline"
|
||||||
|
id="path-effect831"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
weight="33.333333"
|
||||||
|
steps="2"
|
||||||
|
helper_size="0"
|
||||||
|
apply_no_weight="true"
|
||||||
|
apply_with_weight="true"
|
||||||
|
only_selected="false" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="bspline"
|
||||||
|
id="path-effect827"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
weight="33.333333"
|
||||||
|
steps="2"
|
||||||
|
helper_size="0"
|
||||||
|
apply_no_weight="true"
|
||||||
|
apply_with_weight="true"
|
||||||
|
only_selected="false" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="bspline"
|
||||||
|
id="path-effect823"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
weight="33.333333"
|
||||||
|
steps="2"
|
||||||
|
helper_size="0"
|
||||||
|
apply_no_weight="true"
|
||||||
|
apply_with_weight="true"
|
||||||
|
only_selected="false" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="bspline"
|
||||||
|
id="path-effect819"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
weight="33.333333"
|
||||||
|
steps="2"
|
||||||
|
helper_size="0"
|
||||||
|
apply_no_weight="true"
|
||||||
|
apply_with_weight="true"
|
||||||
|
only_selected="false" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="bspline"
|
||||||
|
id="path-effect815"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
weight="33.333333"
|
||||||
|
steps="2"
|
||||||
|
helper_size="0"
|
||||||
|
apply_no_weight="true"
|
||||||
|
apply_with_weight="true"
|
||||||
|
only_selected="false" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="bspline"
|
||||||
|
id="path-effect811"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
weight="33.333333"
|
||||||
|
steps="2"
|
||||||
|
helper_size="0"
|
||||||
|
apply_no_weight="true"
|
||||||
|
apply_with_weight="true"
|
||||||
|
only_selected="false" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="bspline"
|
||||||
|
id="path-effect557"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
weight="33.333333"
|
||||||
|
steps="2"
|
||||||
|
helper_size="0"
|
||||||
|
apply_no_weight="true"
|
||||||
|
apply_with_weight="true"
|
||||||
|
only_selected="false" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="bspline"
|
||||||
|
id="path-effect553"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
weight="33.333333"
|
||||||
|
steps="2"
|
||||||
|
helper_size="0"
|
||||||
|
apply_no_weight="true"
|
||||||
|
apply_with_weight="true"
|
||||||
|
only_selected="false" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="bspline"
|
||||||
|
id="path-effect286"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
weight="33.333333"
|
||||||
|
steps="2"
|
||||||
|
helper_size="0"
|
||||||
|
apply_no_weight="true"
|
||||||
|
apply_with_weight="true"
|
||||||
|
only_selected="false" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="bspline"
|
||||||
|
id="path-effect165"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
weight="33.333333"
|
||||||
|
steps="2"
|
||||||
|
helper_size="0"
|
||||||
|
apply_no_weight="true"
|
||||||
|
apply_with_weight="true"
|
||||||
|
only_selected="false" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="bspline"
|
||||||
|
id="path-effect46"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
weight="33.333333"
|
||||||
|
steps="2"
|
||||||
|
helper_size="0"
|
||||||
|
apply_no_weight="true"
|
||||||
|
apply_with_weight="true"
|
||||||
|
only_selected="false" />
|
||||||
|
</defs>
|
||||||
|
<g
|
||||||
|
inkscape:label="图层 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<path
|
||||||
|
style="fill:#49cf5a;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:10;stroke-opacity:1"
|
||||||
|
d="M 15,0 C 11.667167,0 5.0005002,0 1.6666668,3.3339 c -3.3338333,3.3339 -3.3338333,10.000433 -3.3338333,26.667366 0,16.666934 0,43.333067 0,59.999801 0,16.666733 0,23.333263 3.3339,26.666093 C 5.0006335,120 11.667167,120 28.3341,120 c 16.666933,0 43.333067,0 59.999799,0 16.666731,0 23.333261,0 26.666101,-3.3329 3.33283,-3.3329 3.33283,-9.99943 3.33283,-27.499715 0,-17.500285 0,-45.833052 0,-62.499768 0,-16.666717 0,-21.666617 -3.3329,-24.167117 C 111.66703,0 105.0005,0 88.333566,0 71.666633,0 45.0005,0 18.332833,0 c 0,0 0,0 -3.332833,0 z"
|
||||||
|
id="path44"
|
||||||
|
inkscape:path-effect="#path-effect46"
|
||||||
|
inkscape:original-d="M 18.332833,0 C 11.667167,0.001 5.0005002,0.001 -1.6671665,0 c 10e-4,6.6678 10e-4,13.334333 0,20 10e-4,26.6682 10e-4,53.334333 0,80 10e-4,6.6678 10e-4,13.33433 0,20 6.6678,0.001 13.3343335,0.001 19.9999995,0 26.6682,0.001 53.334334,0.001 80,0 6.667797,0.001 13.334327,0.001 19.999997,0 0.001,-6.6658 0.001,-13.33233 0,-20 0.001,-28.3329 0.001,-56.665667 0,-85 0.001,-4.9991 0.001,-9.999 0,-15 -6.6658,0.001 -13.33233,0.001 -19.999997,0 -26.6662,0.001 -53.332333,0.001 -80,0 0,0 10e-4,0.001 0,0 z" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m -55,55 c -1.665667,-1.665667 -3.332333,-3.332333 -4.999516,-3.332817 -1.667184,-4.83e-4 -3.333817,1.66615 -3.3333,3.333333 C -63.3323,56.6677 -61.665667,58.334333 -60,60"
|
||||||
|
id="path555"
|
||||||
|
inkscape:path-effect="#path-effect557"
|
||||||
|
inkscape:original-d="m -55,55 c -1.665667,-1.665667 -3.332333,-3.332333 -5,-5 -1.6657,1.6677 -3.332333,3.334333 -5,5 1.6677,1.6677 3.334333,3.334333 5,5" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m -60,60 c 3.334333,3.334333 6.667667,6.667667 10,10"
|
||||||
|
id="path809"
|
||||||
|
inkscape:path-effect="#path-effect811"
|
||||||
|
inkscape:original-d="m -60,60 c 3.334333,3.334333 6.667667,6.667667 10,10" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m -55,55 c 3.334333,3.334333 6.667667,6.667667 10,10"
|
||||||
|
id="path813"
|
||||||
|
inkscape:path-effect="#path-effect815"
|
||||||
|
inkscape:original-d="m -55,55 c 3.334333,3.334333 6.667667,6.667667 10,10" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m -50,70 c 1.667667,1.667667 3.334333,3.334333 5.000517,3.333817 C -43.3333,73.3333 -41.666667,71.666667 -40,70"
|
||||||
|
id="path817"
|
||||||
|
inkscape:path-effect="#path-effect819"
|
||||||
|
inkscape:original-d="m -50,70 c 1.667667,1.667667 3.334333,3.334333 5,5 1.6677,-1.6657 3.334333,-3.332333 5,-5" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m -40,70 c 5,-5 10,-10 15,-15"
|
||||||
|
id="path821"
|
||||||
|
inkscape:path-effect="#path-effect823"
|
||||||
|
inkscape:original-d="m -40,70 c 5.001,-4.999 10.001,-9.999 15,-15" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m -45,65 c 5,-5 10,-10 15,-15"
|
||||||
|
id="path825"
|
||||||
|
inkscape:path-effect="#path-effect827"
|
||||||
|
inkscape:original-d="m -45,65 c 5.001,-4.999 10.001,-9.999 15,-15" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m -25,55 c 1.666667,-1.666667 3.333333,-3.333333 3.333816,-4.999516 4.84e-4,-1.666184 -1.666149,-3.332817 -3.333332,-3.333301 C -26.6667,46.6667 -28.333333,48.333333 -30,50"
|
||||||
|
id="path829"
|
||||||
|
inkscape:path-effect="#path-effect831"
|
||||||
|
inkscape:original-d="m -25,55 c 1.667667,-1.665667 3.334333,-3.332333 5,-5 -1.6657,-1.6657 -3.332333,-3.332333 -5,-5 -1.6657,1.6677 -3.332333,3.334333 -5,5" />
|
||||||
|
<path
|
||||||
|
style="fill:#000000;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="M 60,50 C 50,60 40.0002,69.9998 34.166767,75.833233 28.333333,81.666667 26.6667,83.3333 25.000517,83.333817 23.334333,83.334333 21.6677,81.6677 19.167683,79.167683 16.667667,76.667667 13.3344,73.3344 10.834367,70.834367 8.334333,68.334333 6.6677,66.6677 6.6671835,65.000517 6.666667,63.333333 8.3333,61.6667 10.000484,61.667184 c 1.667183,4.83e-4 3.333849,1.667149 5.833883,4.167183 C 18.3344,68.3344 21.667667,71.667667 25,75"
|
||||||
|
id="path946"
|
||||||
|
inkscape:path-effect="#path-effect948"
|
||||||
|
inkscape:original-d="M 60,50 C 50.001,60.001 40.0012,70.0008 30,80 28.334333,81.667667 26.6677,83.3343 25,85 23.334333,83.334333 21.6677,81.6677 20,80 16.667667,76.667667 13.3344,73.3344 10,70 8.334333,68.334333 6.6677,66.6677 5,65 c 1.667667,-1.665667 3.3343,-3.3323 5,-5 1.667667,1.667667 3.334333,3.334333 5,5 3.3344,3.3344 6.667667,6.667667 10,10" />
|
||||||
|
<path
|
||||||
|
style="fill:#000000;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="M 25,75 C 35,65 45,55 50.83335,49.16665 c 5.83335,-5.83335 7.499983,-7.499983 9.167167,-7.499467 1.667183,5.17e-4 3.333816,1.66715 3.333299,3.333334 C 63.3333,46.6667 61.666667,48.333333 60,50"
|
||||||
|
id="path950"
|
||||||
|
inkscape:path-effect="#path-effect952"
|
||||||
|
inkscape:original-d="m 25,75 c 10.001,-9.999 20.001,-19.999 30,-30 1.6677,-1.6657 3.334333,-3.332333 5,-5 1.6677,1.6677 3.334333,3.334333 5,5 -1.6657,1.6677 -3.332333,3.334333 -5,5" />
|
||||||
|
<path
|
||||||
|
style="fill:#ff0000;fill-opacity:0.950941"
|
||||||
|
id="path2558"
|
||||||
|
sodipodi:type="arc"
|
||||||
|
sodipodi:cx="60"
|
||||||
|
sodipodi:cy="30"
|
||||||
|
sodipodi:rx="5"
|
||||||
|
sodipodi:ry="5"
|
||||||
|
sodipodi:start="0"
|
||||||
|
sodipodi:end="6.2506349"
|
||||||
|
sodipodi:arc-type="slice"
|
||||||
|
d="m 65,30 a 5,5 0 0 1 -4.959312,4.999834 5,5 0 0 1 -5.040026,-4.918462 5,5 0 0 1 4.877286,-5.079882 5,5 0 0 1 5.119403,4.835787 L 60,30 Z" />
|
||||||
|
<rect
|
||||||
|
style="fill:#ff0000;fill-opacity:0.950941"
|
||||||
|
id="rect2693"
|
||||||
|
width="40"
|
||||||
|
height="10"
|
||||||
|
x="60"
|
||||||
|
y="25" />
|
||||||
|
<path
|
||||||
|
style="fill:#ff0000;fill-opacity:0.950941"
|
||||||
|
id="path2717"
|
||||||
|
sodipodi:type="arc"
|
||||||
|
sodipodi:cx="105"
|
||||||
|
sodipodi:cy="30"
|
||||||
|
sodipodi:rx="5"
|
||||||
|
sodipodi:ry="5"
|
||||||
|
sodipodi:start="0"
|
||||||
|
sodipodi:end="6.2506349"
|
||||||
|
sodipodi:arc-type="slice"
|
||||||
|
d="m 110,30 a 5,5 0 0 1 -4.95931,4.999834 5,5 0 0 1 -5.04003,-4.918462 5,5 0 0 1 4.87729,-5.079882 5,5 0 0 1 5.1194,4.835787 L 105,30 Z" />
|
||||||
|
<rect
|
||||||
|
style="fill:#ff0000;fill-opacity:0.950941"
|
||||||
|
id="rect2821"
|
||||||
|
width="5"
|
||||||
|
height="10"
|
||||||
|
x="100"
|
||||||
|
y="25" />
|
||||||
|
<path
|
||||||
|
style="fill:#ffff00;fill-opacity:0.950941"
|
||||||
|
id="path2925"
|
||||||
|
sodipodi:type="arc"
|
||||||
|
sodipodi:cx="65"
|
||||||
|
sodipodi:cy="60"
|
||||||
|
sodipodi:rx="5"
|
||||||
|
sodipodi:ry="5"
|
||||||
|
sodipodi:start="0"
|
||||||
|
sodipodi:end="6.2506349"
|
||||||
|
sodipodi:arc-type="slice"
|
||||||
|
d="m 70,60 a 5,5 0 0 1 -4.959312,4.999834 5,5 0 0 1 -5.040026,-4.918462 5,5 0 0 1 4.877286,-5.079882 5,5 0 0 1 5.119403,4.835787 L 65,60 Z" />
|
||||||
|
<rect
|
||||||
|
style="fill:#ffff00;fill-opacity:0.950941"
|
||||||
|
id="rect2949"
|
||||||
|
width="40"
|
||||||
|
height="10"
|
||||||
|
x="65"
|
||||||
|
y="55" />
|
||||||
|
<path
|
||||||
|
style="fill:#ffff00;fill-opacity:0.950941"
|
||||||
|
id="path2973"
|
||||||
|
sodipodi:type="arc"
|
||||||
|
sodipodi:cx="105"
|
||||||
|
sodipodi:cy="60"
|
||||||
|
sodipodi:rx="5"
|
||||||
|
sodipodi:ry="5"
|
||||||
|
sodipodi:start="0"
|
||||||
|
sodipodi:end="6.2506349"
|
||||||
|
sodipodi:arc-type="slice"
|
||||||
|
d="m 110,60 a 5,5 0 0 1 -4.95931,4.999834 5,5 0 0 1 -5.04003,-4.918462 5,5 0 0 1 4.87729,-5.079882 5,5 0 0 1 5.1194,4.835787 L 105,60 Z" />
|
||||||
|
<path
|
||||||
|
style="fill:#00ffff;fill-opacity:0.950941"
|
||||||
|
id="path2975"
|
||||||
|
sodipodi:type="arc"
|
||||||
|
sodipodi:cx="60"
|
||||||
|
sodipodi:cy="85"
|
||||||
|
sodipodi:rx="5"
|
||||||
|
sodipodi:ry="5"
|
||||||
|
sodipodi:start="0"
|
||||||
|
sodipodi:end="6.2506349"
|
||||||
|
sodipodi:arc-type="slice"
|
||||||
|
d="m 65,85 a 5,5 0 0 1 -4.959312,4.999834 5,5 0 0 1 -5.040026,-4.918462 5,5 0 0 1 4.877286,-5.079882 5,5 0 0 1 5.119403,4.835787 L 60,85 Z" />
|
||||||
|
<rect
|
||||||
|
style="fill:#00ffff;fill-opacity:0.950941"
|
||||||
|
id="rect2999"
|
||||||
|
width="45"
|
||||||
|
height="10"
|
||||||
|
x="60"
|
||||||
|
y="80" />
|
||||||
|
<path
|
||||||
|
style="fill:#00ffff;fill-opacity:0.950941"
|
||||||
|
id="path3023"
|
||||||
|
sodipodi:type="arc"
|
||||||
|
sodipodi:cx="105.00265"
|
||||||
|
sodipodi:cy="85.16272"
|
||||||
|
sodipodi:rx="5"
|
||||||
|
sodipodi:ry="5"
|
||||||
|
sodipodi:start="0"
|
||||||
|
sodipodi:end="6.2506349"
|
||||||
|
sodipodi:arc-type="slice"
|
||||||
|
d="m 110.00265,85.16272 a 5,5 0 0 1 -4.95932,4.999834 5,5 0 0 1 -5.04002,-4.918462 5,5 0 0 1 4.87729,-5.079882 5,5 0 0 1 5.1194,4.835787 l -4.99735,0.162723 z" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 14 KiB |
BIN
images/up.png
Normal file
After Width: | Height: | Size: 9.7 KiB |
BIN
images/upload.png
Normal file
After Width: | Height: | Size: 4.1 KiB |
64
resource/current.qss
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
/*去掉item虚线边框*/
|
||||||
|
QListWidget, QListView, QTreeWidget, QTreeView {
|
||||||
|
outline: 0px;
|
||||||
|
}
|
||||||
|
/*设置左侧选项的最小最大宽度,文字颜色和背景颜色*/
|
||||||
|
QListWidget {
|
||||||
|
min-width: 120px;
|
||||||
|
max-width: 120px;
|
||||||
|
color: white;
|
||||||
|
background: black;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
QPushButton {
|
||||||
|
max-width: 120px;
|
||||||
|
color: white;
|
||||||
|
border-top-left-radius:10px;
|
||||||
|
border-top-right-radius:10px;
|
||||||
|
border-bottom-left-radius:10px;
|
||||||
|
border-bottom-right-radius:10px;
|
||||||
|
background: pink;
|
||||||
|
}
|
||||||
|
QPushButton:pressed,
|
||||||
|
QPushButton:pressed:focus {
|
||||||
|
/* 改变背景色 */
|
||||||
|
background-color: #f50057;
|
||||||
|
/* 改变边框风格 */
|
||||||
|
border-style:inset;
|
||||||
|
/* 改变边框风格 */
|
||||||
|
border-style:inset;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPushButton#upload_btn {
|
||||||
|
padding: 3px 20px;
|
||||||
|
text-align:center;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*被选中时的背景颜色和左边框颜色*/
|
||||||
|
QListWidget::item:selected {
|
||||||
|
background: rgb(52, 52, 52);
|
||||||
|
border-right: 4px solid rgb(9, 187, 7);
|
||||||
|
}
|
||||||
|
/*鼠标悬停颜色*/
|
||||||
|
HistoryPanel::item:hover {
|
||||||
|
background: rgb(52, 52, 52);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*右侧的层叠窗口的背景颜色*/
|
||||||
|
QStackedWidget {
|
||||||
|
background: rgb(30, 30, 30);
|
||||||
|
}
|
||||||
|
/*模拟的页面*/
|
||||||
|
QLabel {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
QLineEdit {
|
||||||
|
border: 2px solid rgb(52,52,52);
|
||||||
|
border-top-left-radius:10px;
|
||||||
|
border-top-right-radius:10px;
|
||||||
|
border-bottom-left-radius:10px;
|
||||||
|
border-bottom-right-radius:10px;
|
||||||
|
|
||||||
|
}
|
129
start.py
|
@ -1,91 +1,72 @@
|
||||||
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
from PyQt5.QtWidgets import *
|
||||||
|
from PyQt5.QtGui import *
|
||||||
|
from PyQt5.QtCore import Qt, QSize
|
||||||
|
|
||||||
from PyQt5 import QtCore
|
from tool.UploadTip import UploadTip
|
||||||
from PyQt5.QtGui import QFont, QIcon
|
from tool.ConfigWidget import ConfigView
|
||||||
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QPushButton, QDialog, QLabel, QLineEdit, QGridLayout, QApplication
|
from tool import QSSLoader
|
||||||
from PyQt5.QtCore import Qt
|
|
||||||
from qt_material import apply_stylesheet
|
|
||||||
|
|
||||||
|
class MainWindow(QWidget):
|
||||||
class MainWin(QWidget):
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(MainWin, self).__init__()
|
super(MainWindow, self).__init__()
|
||||||
self.setWindowTitle('上传至阿里云cos')
|
layout = QHBoxLayout(self, spacing=0)
|
||||||
self.resize(400, 500)
|
self.listWidget = QListWidget()
|
||||||
self.setWindowIcon(QIcon('./images/icon.png'))
|
self.resize(800, 600)
|
||||||
|
|
||||||
layout = QVBoxLayout()
|
layout.addWidget(self.listWidget)
|
||||||
|
|
||||||
self.config_btn = QPushButton('配置')
|
# 右侧层叠窗口
|
||||||
# self.config_btn
|
self.stackedWidget = QStackedWidget(self)
|
||||||
self.config_btn.setFixedSize(60, 40)
|
layout.addWidget(self.stackedWidget)
|
||||||
|
|
||||||
|
layout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
|
||||||
self.config_btn.clicked.connect(self.configAction)
|
|
||||||
layout.addStretch()
|
|
||||||
layout.addWidget(self.config_btn, 0, Qt.AlignCenter)
|
|
||||||
layout.addStretch()
|
|
||||||
# layout.addLayout(tip_widget)
|
|
||||||
layout.addStretch()
|
|
||||||
self.setLayout(layout)
|
self.setLayout(layout)
|
||||||
|
self.iniUI()
|
||||||
|
|
||||||
def configAction(self):
|
def iniUI(self):
|
||||||
dialog = QDialog()
|
# 初始化界面
|
||||||
dialog.setMinimumWidth(500)
|
# 通过QListWidget的当前item变化来切换QStackedWidget中的序号
|
||||||
dialog.setWindowTitle("配置oss信息")
|
self.listWidget.currentRowChanged.connect(
|
||||||
access_key_id_label = QLabel('access_key_id:')
|
self.stackedWidget.setCurrentIndex)
|
||||||
access_key_id_text = QLineEdit()
|
# 去掉边框
|
||||||
access_key_secret_label = QLabel('access_key_secret:')
|
# self.listWidget.setFrameShape(QListWidget.NoFrame)
|
||||||
access_key_secret_text = QLineEdit()
|
# # 隐藏滚动条
|
||||||
access_key_secret_text.setEchoMode(QLineEdit.Password)
|
self.listWidget.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
||||||
bucket_name_label = QLabel('bucket_name')
|
self.listWidget.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
||||||
bucket_name_text = QLineEdit()
|
|
||||||
bucket_name_text.setPlaceholderText('设置存储空间名')
|
|
||||||
endpoint_label = QLabel('endpoint')
|
|
||||||
endpoint_text = QLineEdit()
|
|
||||||
endpoint_text.setPlaceholderText('地域节点(如:oss-cn-beijing.aliyuncs.com)')
|
|
||||||
upload_path_label = QLabel('upload_path')
|
|
||||||
upload_path_text = QLineEdit()
|
|
||||||
upload_path_text.setPlaceholderText('上传路径(如:images/)')
|
|
||||||
upload_domain_label = QLabel('upload_domain')
|
|
||||||
upload_domain_text = QLineEdit()
|
|
||||||
upload_domain_text.setPlaceholderText('绑定域名(需要带https://)')
|
|
||||||
dialog_layout = QGridLayout()
|
|
||||||
font = QFont()
|
|
||||||
font.setFamily("Arial")
|
|
||||||
font.setPointSize(50)
|
|
||||||
dialog.setFont(font)
|
|
||||||
dialog_layout.addWidget(access_key_id_label, 0, 0)
|
|
||||||
dialog_layout.addWidget(access_key_id_text, 0, 1)
|
|
||||||
dialog_layout.addWidget(access_key_secret_label, 1, 0)
|
|
||||||
dialog_layout.addWidget(access_key_secret_text, 1, 1)
|
|
||||||
dialog_layout.addWidget(bucket_name_label, 2, 0)
|
|
||||||
dialog_layout.addWidget(bucket_name_text, 2, 1)
|
|
||||||
dialog_layout.addWidget(endpoint_label, 3, 0)
|
|
||||||
dialog_layout.addWidget(endpoint_text, 3, 1)
|
|
||||||
dialog_layout.addWidget(upload_path_label, 4, 0)
|
|
||||||
dialog_layout.addWidget(upload_path_text, 4, 1)
|
|
||||||
dialog_layout.addWidget(upload_domain_label, 5, 0)
|
|
||||||
dialog_layout.addWidget(upload_domain_text, 5, 1)
|
|
||||||
save_btn = QPushButton('保存配置')
|
|
||||||
content = [access_key_id_text.text(), access_key_secret_text.text(), bucket_name_text.text(),
|
|
||||||
endpoint_text.text(), upload_path_text.text(), upload_domain_text.text()]
|
|
||||||
|
|
||||||
save_btn.clicked.connect(lambda: self.save_oss_config(content))
|
# print(os.getcwd())
|
||||||
dialog_layout.addWidget(save_btn, 6, 1)
|
self.upload_item = QListWidgetItem(
|
||||||
dialog.setLayout(dialog_layout)
|
QIcon(QPixmap(os.getcwd()+'/images/upload.png')), '上传区', self.listWidget)
|
||||||
# 设置窗口的属性为ApplicationModal模态,用户只有关闭弹窗后,才能关闭主界面
|
self.set_item = QListWidgetItem(
|
||||||
dialog.setWindowModality(QtCore.Qt.ApplicationModal)
|
QIcon(QPixmap(os.getcwd()+'/images/setting_icon.png')), '配置区域')
|
||||||
dialog.exec_()
|
self.upload_item.setSizeHint(QSize(16777215, 60))
|
||||||
|
# 文字居中
|
||||||
|
self.upload_item.setTextAlignment(Qt.AlignCenter)
|
||||||
|
|
||||||
|
self.set_item.setSizeHint(QSize(16777215, 60))
|
||||||
|
# 文字居中
|
||||||
|
self.set_item.setTextAlignment(Qt.AlignCenter)
|
||||||
|
|
||||||
|
self.listWidget.addItem(self.upload_item)
|
||||||
|
self.listWidget.addItem(self.set_item)
|
||||||
|
upload_widget = UploadTip()
|
||||||
|
config_widget = ConfigView()
|
||||||
|
|
||||||
|
self.stackedWidget.addWidget(upload_widget)
|
||||||
|
self.stackedWidget.addWidget(config_widget)
|
||||||
|
|
||||||
def save_oss_config(self, content):
|
|
||||||
print(content)
|
|
||||||
for i in content:
|
|
||||||
print(i)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
app = QApplication(sys.argv)
|
app = QApplication(sys.argv)
|
||||||
main = MainWin()
|
main = MainWindow()
|
||||||
apply_stylesheet(app, theme='dark_yellow.xml')
|
style_file = 'resource/current.qss'
|
||||||
|
style_sheet = QSSLoader.QSSLoader.read_qss_file(style_file)
|
||||||
|
# apply_stylesheet(app, theme='light_blue.xml')
|
||||||
app.setWindowIcon(QIcon('./images/icon.svg'))
|
app.setWindowIcon(QIcon('./images/icon.svg'))
|
||||||
|
main.setStyleSheet(style_sheet)
|
||||||
|
|
||||||
main.show()
|
main.show()
|
||||||
sys.exit(app.exec_())
|
sys.exit(app.exec_())
|
||||||
|
|
64
test/ConfigView.py
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from PyQt5 import QtCore
|
||||||
|
from PyQt5.QtWidgets import *
|
||||||
|
from PyQt5.QtGui import *
|
||||||
|
from PyQt5.QtCore import Qt
|
||||||
|
|
||||||
|
from ListWidgetItem import ListWidgetItem
|
||||||
|
|
||||||
|
class ConfigView(QLabel):
|
||||||
|
def __init__(self):
|
||||||
|
super(ConfigView, self).__init__()
|
||||||
|
self.config_view=QLabel()
|
||||||
|
|
||||||
|
def configAction(self):
|
||||||
|
dialog = QDialog()
|
||||||
|
# dialog.resize(300,200)
|
||||||
|
dialog.setMaximumSize(500 ,400)
|
||||||
|
dialog.setWindowTitle("配置oss信息")
|
||||||
|
access_key_id_label = QLabel('access_key_id:')
|
||||||
|
access_key_id_text = QLineEdit()
|
||||||
|
access_key_secret_label = QLabel('access_key_secret:')
|
||||||
|
access_key_secret_text = QLineEdit()
|
||||||
|
access_key_secret_text.setEchoMode(QLineEdit.Password)
|
||||||
|
bucket_name_label = QLabel('bucket_name')
|
||||||
|
bucket_name_text = QLineEdit()
|
||||||
|
bucket_name_text.setPlaceholderText('设置存储空间名')
|
||||||
|
endpoint_label = QLabel('endpoint')
|
||||||
|
endpoint_text = QLineEdit()
|
||||||
|
endpoint_text.setPlaceholderText('地域节点(如:oss-cn-beijing.aliyuncs.com)')
|
||||||
|
upload_path_label = QLabel('upload_path')
|
||||||
|
upload_path_text = QLineEdit()
|
||||||
|
upload_path_text.setPlaceholderText('上传路径(如:images/)')
|
||||||
|
upload_domain_label = QLabel('upload_domain')
|
||||||
|
upload_domain_text = QLineEdit()
|
||||||
|
upload_domain_text.setPlaceholderText('绑定域名(需要带https://)')
|
||||||
|
dialog_layout = QGridLayout()
|
||||||
|
font = QFont()
|
||||||
|
font.setFamily("Arial")
|
||||||
|
font.setPointSize(50)
|
||||||
|
dialog.setFont(font)
|
||||||
|
dialog_layout.addWidget(access_key_id_label, 0, 0)
|
||||||
|
dialog_layout.addWidget(access_key_id_text, 0, 1)
|
||||||
|
dialog_layout.addWidget(access_key_secret_label, 1, 0)
|
||||||
|
dialog_layout.addWidget(access_key_secret_text, 1, 1)
|
||||||
|
dialog_layout.addWidget(bucket_name_label, 2, 0)
|
||||||
|
dialog_layout.addWidget(bucket_name_text, 2, 1)
|
||||||
|
dialog_layout.addWidget(endpoint_label, 3, 0)
|
||||||
|
dialog_layout.addWidget(endpoint_text, 3, 1)
|
||||||
|
dialog_layout.addWidget(upload_path_label, 4, 0)
|
||||||
|
dialog_layout.addWidget(upload_path_text, 4, 1)
|
||||||
|
dialog_layout.addWidget(upload_domain_label, 5, 0)
|
||||||
|
dialog_layout.addWidget(upload_domain_text, 5, 1)
|
||||||
|
save_btn = QPushButton('保存配置')
|
||||||
|
content = [access_key_id_text.text(), access_key_secret_text.text(), bucket_name_text.text(),
|
||||||
|
endpoint_text.text(), upload_path_text.text(), upload_domain_text.text()]
|
||||||
|
|
||||||
|
save_btn.clicked.connect(lambda: self.save_oss_config(content))
|
||||||
|
dialog_layout.addWidget(save_btn, 6, 1)
|
||||||
|
dialog.setLayout(dialog_layout)
|
||||||
|
# 设置窗口的属性为ApplicationModal模态,用户只有关闭弹窗后,才能关闭主界面
|
||||||
|
dialog.setWindowModality(QtCore.Qt.ApplicationModal)
|
||||||
|
dialog.exec_()
|
68
tool/ConfigWidget.py
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
from PyQt5.QtWidgets import *
|
||||||
|
from tool.FileConfig import *
|
||||||
|
|
||||||
|
|
||||||
|
class ConfigView(QWidget):
|
||||||
|
def __init__(self):
|
||||||
|
super(ConfigView, self).__init__()
|
||||||
|
layout = QGridLayout()
|
||||||
|
|
||||||
|
self.access_key_id_label = QLabel('access_key_id:')
|
||||||
|
self.access_key_id_text = QLineEdit()
|
||||||
|
self.access_key_secret_label = QLabel('access_key_secret:')
|
||||||
|
self.access_key_secret_text = QLineEdit()
|
||||||
|
self.access_key_secret_text.setEchoMode(QLineEdit.Password)
|
||||||
|
self.bucket_name_label = QLabel('bucket_name')
|
||||||
|
self.bucket_name_text = QLineEdit()
|
||||||
|
self.bucket_name_text.setPlaceholderText('设置存储空间名')
|
||||||
|
self.endpoint_label = QLabel('endpoint')
|
||||||
|
self.endpoint_text = QLineEdit()
|
||||||
|
self.endpoint_text.setPlaceholderText('地域节点(如:oss-cn-beijing.aliyuncs.com)')
|
||||||
|
self.upload_path_label = QLabel('upload_path')
|
||||||
|
self.upload_path_text = QLineEdit()
|
||||||
|
self.upload_path_text.setPlaceholderText('上传路径(如:images/)')
|
||||||
|
self.upload_domain_label = QLabel('upload_domain')
|
||||||
|
self.upload_domain_text = QLineEdit()
|
||||||
|
self.upload_domain_text.setPlaceholderText('绑定域名(需要带https://)')
|
||||||
|
self.set_confirm = QPushButton('保存')
|
||||||
|
self.set_confirm.setObjectName('set_confirm')
|
||||||
|
self.set_default = QPushButton('设为默认图床')
|
||||||
|
self.set_default.setCheckable(False)
|
||||||
|
self.set_default.setObjectName('default_btn')
|
||||||
|
btn_layout = QHBoxLayout()
|
||||||
|
btn_layout.addWidget(self.set_confirm)
|
||||||
|
btn_layout.addWidget(self.set_default)
|
||||||
|
|
||||||
|
# 填充配置文件
|
||||||
|
config = checkConfig(set_config_path())
|
||||||
|
|
||||||
|
if config != None:
|
||||||
|
self.access_key_id_text.setText(config[0])
|
||||||
|
self.access_key_secret_text.setText(config[1])
|
||||||
|
self.bucket_name_text.setText(config[2])
|
||||||
|
self.endpoint_text.setText(config[3])
|
||||||
|
self.upload_path_text.setText(config[4])
|
||||||
|
self.upload_domain_text.setText(config[5])
|
||||||
|
|
||||||
|
self.set_confirm.clicked.connect(self.save_config)
|
||||||
|
|
||||||
|
layout.addWidget(self.access_key_id_label, 0, 0)
|
||||||
|
layout.addWidget(self.access_key_id_text, 0, 1)
|
||||||
|
layout.addWidget(self.access_key_secret_label, 1, 0)
|
||||||
|
layout.addWidget(self.access_key_secret_text, 1, 1)
|
||||||
|
layout.addWidget(self.bucket_name_label, 2, 0)
|
||||||
|
layout.addWidget(self.bucket_name_text, 2, 1)
|
||||||
|
layout.addWidget(self.endpoint_label, 3, 0)
|
||||||
|
layout.addWidget(self.endpoint_text, 3, 1)
|
||||||
|
layout.addWidget(self.upload_path_label, 4, 0)
|
||||||
|
layout.addWidget(self.upload_path_text, 4, 1)
|
||||||
|
layout.addWidget(self.upload_domain_label, 5, 0)
|
||||||
|
layout.addWidget(self.upload_domain_text, 5, 1)
|
||||||
|
layout.addItem(btn_layout, 6, 1)
|
||||||
|
|
||||||
|
self.setLayout(layout)
|
||||||
|
|
||||||
|
def save_config(self):
|
||||||
|
saveConfig(self.access_key_id_text.text(), self.access_key_secret_text.text(), self.bucket_name_text.text(),
|
||||||
|
self.endpoint_text.text(),
|
||||||
|
self.upload_path_text.text(), self.upload_domain_text.text())
|
65
tool/FileConfig.py
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import platform
|
||||||
|
|
||||||
|
|
||||||
|
config_json = '''
|
||||||
|
{
|
||||||
|
"OSS_ACCESS_KEY_ID": "",
|
||||||
|
"OSS_ACCESS_KEY_SECRET": "",
|
||||||
|
"OSS_BUCKET": "",
|
||||||
|
"OSS_ENDPOINT": "",
|
||||||
|
"UPLOAD_PATH": "",
|
||||||
|
"UPLOAD_DOMAIN": ""
|
||||||
|
}
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
def set_config_path():
|
||||||
|
# 创建Linux下配置文件目录
|
||||||
|
if platform.system() == 'Linux':
|
||||||
|
#
|
||||||
|
config_path = os.path.expanduser('~') + '/.config/PyQtPicUpload/'
|
||||||
|
if not os.path.exists(config_path):
|
||||||
|
os.mkdir(config_path)
|
||||||
|
# print(config_path)
|
||||||
|
config_file = config_path + 'config.json'
|
||||||
|
return config_file
|
||||||
|
|
||||||
|
# 检测配置文件
|
||||||
|
def checkConfig(config_file):
|
||||||
|
try:
|
||||||
|
with open(config_file, 'r') as file:
|
||||||
|
config = json.load(file)
|
||||||
|
# print(str(config))
|
||||||
|
access_key_id = config['OSS_ACCESS_KEY_ID']
|
||||||
|
# print(access_key_id)
|
||||||
|
access_key_secret = config['OSS_ACCESS_KEY_SECRET']
|
||||||
|
# print(access_key_secret)
|
||||||
|
bucket_name = config['OSS_BUCKET']
|
||||||
|
endpoint = config['OSS_ENDPOINT']
|
||||||
|
upload_path = config['UPLOAD_PATH']
|
||||||
|
upload_domain = config['UPLOAD_DOMAIN']
|
||||||
|
# print(upload_domain)
|
||||||
|
for param in (access_key_id, access_key_secret, bucket_name, endpoint, upload_path, upload_domain):
|
||||||
|
assert '' != param, '请配置上传参数!'
|
||||||
|
return [access_key_id, access_key_secret, bucket_name, endpoint, upload_path, upload_domain]
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def saveConfig(access_key_id, access_key_secret, bucket_name, endpoint, upload_path, upload_domain):
|
||||||
|
|
||||||
|
config_file = set_config_path()
|
||||||
|
|
||||||
|
with open(config_file, 'w+') as file:
|
||||||
|
json_config = {
|
||||||
|
"OSS_ACCESS_KEY_ID": access_key_id,
|
||||||
|
"OSS_ACCESS_KEY_SECRET": access_key_secret,
|
||||||
|
"OSS_BUCKET": bucket_name,
|
||||||
|
"OSS_ENDPOINT": endpoint,
|
||||||
|
"UPLOAD_PATH": upload_path if upload_path[-1] == '/' else upload_path + '/',
|
||||||
|
"UPLOAD_DOMAIN": upload_domain if upload_domain[-1] == '/' else upload_domain + '/'
|
||||||
|
}
|
||||||
|
file.write(json.dumps(json_config))
|
8
tool/QSSLoader.py
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
class QSSLoader:
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def read_qss_file(qss_file_name):
|
||||||
|
with open(qss_file_name, 'r', encoding='UTF-8') as file:
|
||||||
|
return file.read()
|
173
tool/UploadTip.py
Normal file
|
@ -0,0 +1,173 @@
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import os
|
||||||
|
import oss2
|
||||||
|
from PyQt5.QtCore import QSize, Qt, QThread, pyqtSignal, pyqtSlot
|
||||||
|
from PyQt5.QtWidgets import *
|
||||||
|
from PyQt5 import QtCore
|
||||||
|
from PyQt5.QtGui import QPixmap
|
||||||
|
from tool import FileConfig
|
||||||
|
import notify2
|
||||||
|
|
||||||
|
|
||||||
|
class UploadAction(QThread):
|
||||||
|
status = pyqtSignal(str)
|
||||||
|
|
||||||
|
def __init__(self, filepath):
|
||||||
|
super(UploadAction, self).__init__()
|
||||||
|
try:
|
||||||
|
with open(FileConfig.set_config_path(), 'r') as file:
|
||||||
|
config = json.load(file)
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
self.status.emit(False)
|
||||||
|
|
||||||
|
self.filepath = filepath
|
||||||
|
# print(str(config))
|
||||||
|
self.access_key_id = config['OSS_ACCESS_KEY_ID']
|
||||||
|
# print(access_key_id)
|
||||||
|
self.access_key_secret = config['OSS_ACCESS_KEY_SECRET']
|
||||||
|
# print(access_key_secret)
|
||||||
|
self.bucket_name = config['OSS_BUCKET']
|
||||||
|
self.endpoint = config['OSS_ENDPOINT']
|
||||||
|
self.upload_path = config['UPLOAD_PATH'] if config['UPLOAD_PATH'][-1] == '/' else config['UPLOAD_PATH'] + '/'
|
||||||
|
# 在域名后面添加 /
|
||||||
|
self.upload_domain = config['UPLOAD_DOMAIN'] if config['UPLOAD_DOMAIN'][-1] == '/' else config[
|
||||||
|
'UPLOAD_DOMAIN'] + '/'
|
||||||
|
|
||||||
|
def percentage(self, consumed_bytes, total_bytes):
|
||||||
|
"""进度条回调函数,计算当前完成的百分比
|
||||||
|
:param consumed_bytes: 已经上传/下载的数据量
|
||||||
|
:param total_bytes: 总数据量
|
||||||
|
"""
|
||||||
|
if total_bytes:
|
||||||
|
rate = int(100 * (float(consumed_bytes) / float(total_bytes)))
|
||||||
|
print('\r{0}% '.format(rate))
|
||||||
|
sys.stdout.flush()
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
print('filepath:',self.filepath)
|
||||||
|
# 创建Bucket对象,所有Object相关的接口都可以通过Bucket对象来进行
|
||||||
|
bucket = oss2.Bucket(oss2.Auth(self.access_key_id, self.access_key_secret), self.endpoint, self.bucket_name)
|
||||||
|
# 必须以二进制的方式打开文件。
|
||||||
|
# 填写本地文件的完整路径。如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件。
|
||||||
|
with open(self.filepath, 'rb') as fileobj:
|
||||||
|
# 填写Object完整路径。Object完整路径中不能包含Bucket名称。
|
||||||
|
upload_name = self.upload_path + self.filepath.split('/')[-1]
|
||||||
|
bucket.put_object(upload_name, fileobj, progress_callback=self.percentage)
|
||||||
|
self.status.emit(self.upload_domain + upload_name)
|
||||||
|
# print('result_url:',self.upload_domain + upload_name)
|
||||||
|
class UploadTip(QWidget):
|
||||||
|
def __init__(self):
|
||||||
|
super(UploadTip, self).__init__()
|
||||||
|
self.pic_show = QLabel()
|
||||||
|
# self.resize(300,500)
|
||||||
|
# self.pic_show.setMaximumSize(300, 400)
|
||||||
|
self.pic_show.setObjectName('pic_show')
|
||||||
|
# self.pic_show.setStyleSheet('align:center')
|
||||||
|
self.pic_show.setAlignment(Qt.AlignCenter)
|
||||||
|
|
||||||
|
self.pic_show.setPixmap(
|
||||||
|
QPixmap(os.getcwd() + '/images/upload.png'))
|
||||||
|
|
||||||
|
self.pic_show.setStyleSheet('border:4px solid;')
|
||||||
|
# self.pic_show.
|
||||||
|
# .scaled(self.pic_show.size(), aspectRatioMode=QtCore.Qt.KeepAspectRatio)
|
||||||
|
|
||||||
|
self.pic_tip = QLabel('Ctrl + V 粘贴图片')
|
||||||
|
self.pic_tip.setAlignment(QtCore.Qt.AlignCenter)
|
||||||
|
|
||||||
|
self.tip_layout = QVBoxLayout(self)
|
||||||
|
self.tip_layout.addStretch()
|
||||||
|
self.tip_layout.addWidget(self.pic_show)
|
||||||
|
self.tip_layout.addStretch()
|
||||||
|
|
||||||
|
self.tip_layout.addWidget(self.pic_tip)
|
||||||
|
# self.tip_layout.addStretch()
|
||||||
|
self.upload_btn = QPushButton('点击上传')
|
||||||
|
self.upload_btn.setObjectName('upload_btn')
|
||||||
|
|
||||||
|
# self.upload_btn.set(Qt.AlignCenter)
|
||||||
|
|
||||||
|
self.tip_layout.addWidget(self.upload_btn, 0, Qt.AlignCenter)
|
||||||
|
|
||||||
|
# layout.setSpacing(0)
|
||||||
|
# 美化风格
|
||||||
|
# self.setStyleSheet(qt_material.apply_stylesheet(self,''))
|
||||||
|
self.createActions()
|
||||||
|
|
||||||
|
self.upload_btn.clicked.connect(self.upload_action)
|
||||||
|
|
||||||
|
self.restore_path = ''
|
||||||
|
self.setLayout(self.tip_layout)
|
||||||
|
def upload_action(self):
|
||||||
|
if self.restore_path != '':
|
||||||
|
self.upload_btn.setEnabled(False)
|
||||||
|
self.upload_btn.setText('上传中...')
|
||||||
|
self.upload_action.start()
|
||||||
|
|
||||||
|
def upload_status(self, status):
|
||||||
|
# print('upload_status:',status)
|
||||||
|
# 判断上传结果
|
||||||
|
if status:
|
||||||
|
print(status)
|
||||||
|
clipboard = QApplication.clipboard()
|
||||||
|
clipboard.setText('![]('+status+')')
|
||||||
|
notify2.init('OSS上传')
|
||||||
|
notify2.Notification('OSS上传',status,self.restore_path).show()
|
||||||
|
self.upload_btn.setText('点击上传')
|
||||||
|
self.upload_btn.setEnabled(True)
|
||||||
|
else:
|
||||||
|
print('upload error !')
|
||||||
|
os.remove(self.restore_path)
|
||||||
|
|
||||||
|
def createActions(self):
|
||||||
|
pastAction = QAction(self)
|
||||||
|
pastAction.setShortcut("Ctrl+V")
|
||||||
|
pastAction.triggered.connect(self.pasteData)
|
||||||
|
self.addAction((pastAction)) # Activate QAction
|
||||||
|
|
||||||
|
def setImage(self, path):
|
||||||
|
# print(path)
|
||||||
|
image = QPixmap(path)
|
||||||
|
# print(image.width(),image.height())
|
||||||
|
if image.width() > image.height():
|
||||||
|
scale = self.pic_show.width() / image.width()
|
||||||
|
# print('比例:', scale)
|
||||||
|
|
||||||
|
# width=scale*clipboard.pixmap().width()*scale
|
||||||
|
height = image.height() * scale
|
||||||
|
# print('转换后高度:', height)
|
||||||
|
self.pic_show.setPixmap(image.scaled(QSize(self.pic_show.width(), int(height)))) # 用于粘贴图片
|
||||||
|
else:
|
||||||
|
scale = self.pic_show.height() / image.height()
|
||||||
|
# print('比例:', scale)
|
||||||
|
width = image.width() * scale
|
||||||
|
# print('转换后宽度:', width)
|
||||||
|
self.pic_show.setPixmap(image.scaled(QSize(int(width), self.pic_show.height())))
|
||||||
|
self.pic_show.setAlignment(QtCore.Qt.AlignCenter)
|
||||||
|
|
||||||
|
|
||||||
|
def pasteData(self):
|
||||||
|
clipboard = QApplication.clipboard()
|
||||||
|
mimeData = clipboard.mimeData()
|
||||||
|
|
||||||
|
if mimeData.hasImage():
|
||||||
|
|
||||||
|
# 根据时间设置图片文件名
|
||||||
|
file_name = time.strftime('%Y-%m-%d-%H%M%S', time.localtime()) + '.png'
|
||||||
|
# 将图片保存到指定位置
|
||||||
|
self.restore_path = '/tmp/' + file_name
|
||||||
|
clipboard.pixmap().save(self.restore_path, 'PNG')
|
||||||
|
|
||||||
|
# print(restore_path)
|
||||||
|
self.setImage(self.restore_path)
|
||||||
|
elif mimeData.hasText():
|
||||||
|
self.restore_path = clipboard.text()
|
||||||
|
self.setImage(self.restore_path)
|
||||||
|
print("pasted from clipboard")
|
||||||
|
|
||||||
|
# 设置点击事件的信号传递
|
||||||
|
self.upload_action = UploadAction(self.restore_path)
|
||||||
|
self.upload_action.status.connect(self.upload_status)
|