Merge remote-tracking branch 'origin/dev_vite' into StableVersion
@@ -1,4 +1,4 @@
|
||||
VITE_USER_NODE_ENV = 'production'
|
||||
VITE_USER_NODE_ENV = 'development'
|
||||
# VITE_APP_BASE_URL = 'https://aida.com.hk/test'
|
||||
# VITE_APP_BASE_URL = 'http://18.167.251.121:10088'
|
||||
# VITE_APP_BASE_URL = 'https://api.aida.com.hk'
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
<<<<<<< HEAD
|
||||
VITE_USER_NODE_ENV = 'development'
|
||||
VITE_APP_BASE_URL = 'https://test.api.aida.com.hk'
|
||||
# VITE_APP_BASE_URL = 'https://api.aida.com.hk'
|
||||
=======
|
||||
NODE_ENV = 'development'
|
||||
# VUE_APP_BASE_URL = 'https://api.aida.com.hk'
|
||||
VUE_APP_BASE_URL = 'https://test.api.aida.com.hk'
|
||||
>>>>>>> 5d8304ce3ece21dd3200ffffb0c76e3ef55dd213
|
||||
|
||||
# VITE_APP_BASE_URL = 'http://18.167.251.121:10086'
|
||||
# VITE_APP_BASE_URL = 'http://192.168.1.9:5567'
|
||||
|
||||
1
.gitignore
vendored
@@ -23,3 +23,4 @@ dist.rar
|
||||
*.sln
|
||||
*.sw?
|
||||
.eslintrc-auto-import.json
|
||||
components.d.ts
|
||||
|
||||
31
components.d.ts
vendored
@@ -1,31 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
// Generated by unplugin-vue-components
|
||||
// Read more: https://github.com/vuejs/core/pull/3399
|
||||
// biome-ignore lint: disable
|
||||
export {}
|
||||
|
||||
/* prettier-ignore */
|
||||
declare module 'vue' {
|
||||
export interface GlobalComponents {
|
||||
ABadge: typeof import('ant-design-vue/es')['Badge']
|
||||
ACheckbox: typeof import('ant-design-vue/es')['Checkbox']
|
||||
ADrawer: typeof import('ant-design-vue/es')['Drawer']
|
||||
AImage: typeof import('ant-design-vue/es')['Image']
|
||||
AInputNumber: typeof import('ant-design-vue/es')['InputNumber']
|
||||
AModal: typeof import('ant-design-vue/es')['Modal']
|
||||
APagination: typeof import('ant-design-vue/es')['Pagination']
|
||||
APopover: typeof import('ant-design-vue/es')['Popover']
|
||||
ARangePicker: typeof import('ant-design-vue/es')['RangePicker']
|
||||
ASelect: typeof import('ant-design-vue/es')['Select']
|
||||
ASelectOption: typeof import('ant-design-vue/es')['SelectOption']
|
||||
ASlider: typeof import('ant-design-vue/es')['Slider']
|
||||
ASpin: typeof import('ant-design-vue/es')['Spin']
|
||||
ASwitch: typeof import('ant-design-vue/es')['Switch']
|
||||
ATable: typeof import('ant-design-vue/es')['Table']
|
||||
AUpload: typeof import('ant-design-vue/es')['Upload']
|
||||
ElCascader: typeof import('element-plus/es')['ElCascader']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 8.9 KiB |
BIN
public/image/brush/fur.jpg
Normal file
|
After Width: | Height: | Size: 7.3 KiB |
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
BIN
public/image/brush/pen.jpg
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 7.4 KiB |
BIN
public/image/brush/shaded.jpg
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
public/image/brush/spray.jpg
Normal file
|
After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 201 KiB After Width: | Height: | Size: 201 KiB |
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
@@ -1,18 +1,22 @@
|
||||
@font-face {
|
||||
font-family: "iconfont"; /* Project id 4292253 */
|
||||
src: url('iconfont.woff2?t=1727415711578') format('woff2'),
|
||||
url('iconfont.woff?t=1727415711578') format('woff'),
|
||||
url('iconfont.ttf?t=1727415711578') format('truetype');
|
||||
src: url('iconfont.woff2?t=1759888699816') format('woff2'),
|
||||
url('iconfont.woff?t=1759888699816') format('woff'),
|
||||
url('iconfont.ttf?t=1759888699816') format('truetype');
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
font-family: "iconfont" !important;
|
||||
font-size: 1.8rem;
|
||||
font-size: 1.6rem;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.icon-clothes:before {
|
||||
content: "\e8d1";
|
||||
}
|
||||
|
||||
.icon-caizhi:before {
|
||||
content: "\e647";
|
||||
}
|
||||
|
||||
@@ -1,170 +1,219 @@
|
||||
{
|
||||
"id": "",
|
||||
"name": "",
|
||||
"id": "4292253",
|
||||
"name": "aida",
|
||||
"font_family": "iconfont",
|
||||
"css_prefix_text": "icon-",
|
||||
"description": "",
|
||||
"glyphs": [
|
||||
{
|
||||
"icon_id": "124968799",
|
||||
"name": "外套_长款外套1@1x",
|
||||
"font_class": "a-waitao_changkuanwaitao11x",
|
||||
"unicode": "e66c",
|
||||
"unicode_decimal": 58988
|
||||
"icon_id": "20183053",
|
||||
"name": "clothes",
|
||||
"font_class": "clothes",
|
||||
"unicode": "e8d1",
|
||||
"unicode_decimal": 59601
|
||||
},
|
||||
{
|
||||
"icon_id": "125198319",
|
||||
"name": "撤销 返回 撤回 上一步",
|
||||
"font_class": "fanchehui",
|
||||
"unicode": "e626",
|
||||
"unicode_decimal": 58918
|
||||
"icon_id": "15739173",
|
||||
"name": "材质",
|
||||
"font_class": "caizhi",
|
||||
"unicode": "e647",
|
||||
"unicode_decimal": 58951
|
||||
},
|
||||
{
|
||||
"icon_id": "125198320",
|
||||
"name": "撤销 返回 撤回 上一步",
|
||||
"font_class": "chehui",
|
||||
"unicode": "e609",
|
||||
"unicode_decimal": 58889
|
||||
"icon_id": "35023469",
|
||||
"name": "IC-液化",
|
||||
"font_class": "IC-yehua",
|
||||
"unicode": "e61b",
|
||||
"unicode_decimal": 58907
|
||||
},
|
||||
{
|
||||
"icon_id": "125524062",
|
||||
"name": "语言",
|
||||
"font_class": "yuyan",
|
||||
"unicode": "e85f",
|
||||
"unicode_decimal": 59487
|
||||
"icon_id": "12096844",
|
||||
"name": "上一层",
|
||||
"font_class": "shangyiceng",
|
||||
"unicode": "e751",
|
||||
"unicode_decimal": 59217
|
||||
},
|
||||
{
|
||||
"icon_id": "126177191",
|
||||
"name": "标签",
|
||||
"font_class": "biaoqian",
|
||||
"unicode": "e603",
|
||||
"unicode_decimal": 58883
|
||||
"icon_id": "16531912",
|
||||
"name": "上一层",
|
||||
"font_class": "shangyiceng1",
|
||||
"unicode": "e604",
|
||||
"unicode_decimal": 58884
|
||||
},
|
||||
{
|
||||
"icon_id": "126459101",
|
||||
"name": "并集",
|
||||
"font_class": "bingji",
|
||||
"unicode": "e620",
|
||||
"unicode_decimal": 58912
|
||||
"icon_id": "24253227",
|
||||
"name": "下一层",
|
||||
"font_class": "xiayiceng",
|
||||
"unicode": "e68a",
|
||||
"unicode_decimal": 59018
|
||||
},
|
||||
{
|
||||
"icon_id": "126459102",
|
||||
"name": "并集",
|
||||
"font_class": "bingji1",
|
||||
"unicode": "e668",
|
||||
"unicode_decimal": 58984
|
||||
"icon_id": "24253230",
|
||||
"name": "上一层",
|
||||
"font_class": "shangyiceng2",
|
||||
"unicode": "e68b",
|
||||
"unicode_decimal": 59019
|
||||
},
|
||||
{
|
||||
"icon_id": "126901286",
|
||||
"name": "点位",
|
||||
"font_class": "dianwei",
|
||||
"unicode": "e685",
|
||||
"unicode_decimal": 59013
|
||||
},
|
||||
{
|
||||
"icon_id": "130743908",
|
||||
"name": "编辑",
|
||||
"font_class": "bianji",
|
||||
"unicode": "e600",
|
||||
"unicode_decimal": 58880
|
||||
},
|
||||
{
|
||||
"icon_id": "130743909",
|
||||
"name": "圆形",
|
||||
"font_class": "circle",
|
||||
"unicode": "e64f",
|
||||
"unicode_decimal": 58959
|
||||
},
|
||||
{
|
||||
"icon_id": "130743910",
|
||||
"name": "三角形",
|
||||
"font_class": "sanjiaoxing",
|
||||
"unicode": "e615",
|
||||
"unicode_decimal": 58901
|
||||
},
|
||||
{
|
||||
"icon_id": "130743911",
|
||||
"name": "图层",
|
||||
"font_class": "tuceng",
|
||||
"unicode": "e632",
|
||||
"unicode_decimal": 58930
|
||||
},
|
||||
{
|
||||
"icon_id": "130743912",
|
||||
"name": "平移",
|
||||
"font_class": "move",
|
||||
"unicode": "e616",
|
||||
"unicode_decimal": 58902
|
||||
},
|
||||
{
|
||||
"icon_id": "130743913",
|
||||
"name": "橡皮",
|
||||
"font_class": "xiangpi_huaban1",
|
||||
"unicode": "e67b",
|
||||
"unicode_decimal": 59003
|
||||
},
|
||||
{
|
||||
"icon_id": "130743914",
|
||||
"name": "tx-fill-椭圆形",
|
||||
"font_class": "tx-fill-tuoyuanxing",
|
||||
"unicode": "e64c",
|
||||
"unicode_decimal": 58956
|
||||
},
|
||||
{
|
||||
"icon_id": "130743915",
|
||||
"name": "直线",
|
||||
"font_class": "zhixian",
|
||||
"unicode": "e602",
|
||||
"unicode_decimal": 58882
|
||||
},
|
||||
{
|
||||
"icon_id": "130743916",
|
||||
"name": "线",
|
||||
"font_class": "xian",
|
||||
"unicode": "ec5f",
|
||||
"unicode_decimal": 60511
|
||||
},
|
||||
{
|
||||
"icon_id": "130743917",
|
||||
"name": "正方形",
|
||||
"font_class": "checkbox-full",
|
||||
"unicode": "ea6f",
|
||||
"unicode_decimal": 60015
|
||||
},
|
||||
{
|
||||
"icon_id": "130743918",
|
||||
"name": "图层",
|
||||
"font_class": "tuceng1",
|
||||
"unicode": "e62d",
|
||||
"unicode_decimal": 58925
|
||||
},
|
||||
{
|
||||
"icon_id": "130751283",
|
||||
"icon_id": "3663275",
|
||||
"name": "审批",
|
||||
"font_class": "shenpi",
|
||||
"unicode": "e6a1",
|
||||
"unicode_decimal": 59041
|
||||
},
|
||||
{
|
||||
"icon_id": "130751284",
|
||||
"icon_id": "7638976",
|
||||
"name": "用户",
|
||||
"font_class": "yonghu",
|
||||
"unicode": "e617",
|
||||
"unicode_decimal": 58903
|
||||
},
|
||||
{
|
||||
"icon_id": "130751285",
|
||||
"icon_id": "9775414",
|
||||
"name": "使用次数",
|
||||
"font_class": "usetime",
|
||||
"unicode": "e601",
|
||||
"unicode_decimal": 58881
|
||||
},
|
||||
{
|
||||
"icon_id": "130751286",
|
||||
"icon_id": "16843615",
|
||||
"name": "下拉",
|
||||
"font_class": "xiala",
|
||||
"unicode": "e634",
|
||||
"unicode_decimal": 58932
|
||||
},
|
||||
{
|
||||
"icon_id": "1264",
|
||||
"name": "编辑",
|
||||
"font_class": "bianji",
|
||||
"unicode": "e600",
|
||||
"unicode_decimal": 58880
|
||||
},
|
||||
{
|
||||
"icon_id": "755612",
|
||||
"name": "圆形",
|
||||
"font_class": "circle",
|
||||
"unicode": "e64f",
|
||||
"unicode_decimal": 58959
|
||||
},
|
||||
{
|
||||
"icon_id": "3101162",
|
||||
"name": "三角形",
|
||||
"font_class": "sanjiaoxing",
|
||||
"unicode": "e615",
|
||||
"unicode_decimal": 58901
|
||||
},
|
||||
{
|
||||
"icon_id": "6774075",
|
||||
"name": "图层",
|
||||
"font_class": "tuceng",
|
||||
"unicode": "e632",
|
||||
"unicode_decimal": 58930
|
||||
},
|
||||
{
|
||||
"icon_id": "10905244",
|
||||
"name": "平移",
|
||||
"font_class": "move",
|
||||
"unicode": "e616",
|
||||
"unicode_decimal": 58902
|
||||
},
|
||||
{
|
||||
"icon_id": "14421659",
|
||||
"name": "橡皮",
|
||||
"font_class": "xiangpi_huaban1",
|
||||
"unicode": "e67b",
|
||||
"unicode_decimal": 59003
|
||||
},
|
||||
{
|
||||
"icon_id": "14718690",
|
||||
"name": "tx-fill-椭圆形",
|
||||
"font_class": "tx-fill-tuoyuanxing",
|
||||
"unicode": "e64c",
|
||||
"unicode_decimal": 58956
|
||||
},
|
||||
{
|
||||
"icon_id": "17521049",
|
||||
"name": "直线",
|
||||
"font_class": "zhixian",
|
||||
"unicode": "e602",
|
||||
"unicode_decimal": 58882
|
||||
},
|
||||
{
|
||||
"icon_id": "17581689",
|
||||
"name": "线",
|
||||
"font_class": "xian",
|
||||
"unicode": "ec5f",
|
||||
"unicode_decimal": 60511
|
||||
},
|
||||
{
|
||||
"icon_id": "18175800",
|
||||
"name": "正方形",
|
||||
"font_class": "checkbox-full",
|
||||
"unicode": "ea6f",
|
||||
"unicode_decimal": 60015
|
||||
},
|
||||
{
|
||||
"icon_id": "26998795",
|
||||
"name": "图层",
|
||||
"font_class": "tuceng1",
|
||||
"unicode": "e62d",
|
||||
"unicode_decimal": 58925
|
||||
},
|
||||
{
|
||||
"icon_id": "31762941",
|
||||
"name": "点位",
|
||||
"font_class": "dianwei",
|
||||
"unicode": "e685",
|
||||
"unicode_decimal": 59013
|
||||
},
|
||||
{
|
||||
"icon_id": "8722601",
|
||||
"name": "并集",
|
||||
"font_class": "bingji",
|
||||
"unicode": "e620",
|
||||
"unicode_decimal": 58912
|
||||
},
|
||||
{
|
||||
"icon_id": "15192904",
|
||||
"name": "并集",
|
||||
"font_class": "bingji1",
|
||||
"unicode": "e668",
|
||||
"unicode_decimal": 58984
|
||||
},
|
||||
{
|
||||
"icon_id": "17863630",
|
||||
"name": "标签",
|
||||
"font_class": "biaoqian",
|
||||
"unicode": "e603",
|
||||
"unicode_decimal": 58883
|
||||
},
|
||||
{
|
||||
"icon_id": "16399020",
|
||||
"name": "语言",
|
||||
"font_class": "yuyan",
|
||||
"unicode": "e85f",
|
||||
"unicode_decimal": 59487
|
||||
},
|
||||
{
|
||||
"icon_id": "4240742",
|
||||
"name": "撤销 返回 撤回 上一步",
|
||||
"font_class": "fanchehui",
|
||||
"unicode": "e626",
|
||||
"unicode_decimal": 58918
|
||||
},
|
||||
{
|
||||
"icon_id": "6126117",
|
||||
"name": "撤销 返回 撤回 上一步",
|
||||
"font_class": "chehui",
|
||||
"unicode": "e609",
|
||||
"unicode_decimal": 58889
|
||||
},
|
||||
{
|
||||
"icon_id": "33174601",
|
||||
"name": "外套_长款外套1@1x",
|
||||
"font_class": "a-waitao_changkuanwaitao11x",
|
||||
"unicode": "e66c",
|
||||
"unicode_decimal": 58988
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
1
src/assets/icons/CClothes.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1759472135618" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="15482" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M341.12 85.333h373.845A170.667 170.667 0 0 1 835.67 135.34l130.987 130.986a46.933 46.933 0 0 1 8.79 54.187l-82.774 165.547A46.933 46.933 0 0 1 850.688 512h-40.021v298.667a128 128 0 0 1-128 128H341.333a128 128 0 0 1-128-128V512h-40.021a46.933 46.933 0 0 1-41.984-25.941L48.555 320.512a46.933 46.933 0 0 1 8.789-54.187L188.331 135.34a170.667 170.667 0 0 1 120.704-50.006h32.085z m-18.944 85.334h-13.141a85.333 85.333 0 0 0-60.374 25.002L137.26 307.072l59.776 119.595h54.698a46.933 46.933 0 0 1 46.934 46.933v337.067a42.667 42.667 0 0 0 42.666 42.666h341.334a42.667 42.667 0 0 0 42.666-42.666V473.6a46.933 46.933 0 0 1 46.934-46.933h54.698l59.776-119.595L775.34 195.669a85.333 85.333 0 0 0-60.374-25.002h-13.141L575.787 312.49a85.333 85.333 0 0 1-127.574 0L322.176 170.667z m114.176 0L512 255.787l75.648-85.12H436.352z" fill="#2c2c2c" p-id="15483"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
17
src/assets/icons/CHelp.svg
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||
width="64.000000pt" height="64.000000pt" viewBox="0 0 64.000000 64.000000"
|
||||
preserveAspectRatio="xMidYMid meet">
|
||||
|
||||
<g transform="translate(0.000000,64.000000) scale(0.100000,-0.100000)"
|
||||
fill="#000000" stroke="none">
|
||||
<path d="M223 622 c-109 -39 -178 -112 -210 -221 -29 -102 4 -228 82 -306 122
|
||||
-121 328 -121 450 0 91 92 118 241 64 356 -69 146 -241 223 -386 171z m152
|
||||
-146 c68 -29 73 -85 13 -154 -24 -27 -48 -57 -54 -67 -15 -27 -44 -12 -44 22
|
||||
0 18 13 41 41 69 46 47 47 79 3 90 -28 7 -52 -9 -65 -44 -6 -17 -15 -22 -32
|
||||
-20 -30 4 -33 38 -6 72 36 46 84 57 144 32z m-31 -278 c8 -14 7 -21 -6 -34
|
||||
-30 -30 -75 9 -48 42 16 18 39 15 54 -8z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 847 B |
2
src/assets/icons/CLibrary.svg
Normal file
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 24 24" width="512" height="512"><path d="M7,0h-3C1.79,0,0,1.79,0,4v3c0,2.21,1.79,4,4,4h3c2.21,0,4-1.79,4-4v-3C11,1.79,9.21,0,7,0Zm2,7c0,1.1-.9,2-2,2h-3c-1.1,0-2-.9-2-2v-3c0-1.1,.9-2,2-2h3c1.1,0,2,.9,2,2v3Zm11,6h-3c-2.21,0-4,1.79-4,4v3c0,2.21,1.79,4,4,4h3c2.21,0,4-1.79,4-4v-3c0-2.21-1.79-4-4-4Zm2,7c0,1.1-.9,2-2,2h-3c-1.1,0-2-.9-2-2v-3c0-1.1,.9-2,2-2h3c1.1,0,2,.9,2,2v3ZM7,13h-3c-2.21,0-4,1.79-4,4v3c0,2.21,1.79,4,4,4h3c2.21,0,4-1.79,4-4v-3c0-2.21-1.79-4-4-4Zm2,7c0,1.1-.9,2-2,2h-3c-1.1,0-2-.9-2-2v-3c0-1.1,.9-2,2-2h3c1.1,0,2,.9,2,2v3Zm8.18-10.47c.38,.31,.85,.46,1.32,.46s.94-.15,1.32-.46c1.56-1.25,4.18-3.7,4.18-6.06,0-1.92-1.46-3.48-3.25-3.48-.85,0-1.65,.36-2.25,.94-.59-.59-1.39-.94-2.25-.94-1.79,0-3.25,1.56-3.25,3.48,0,2.35,2.62,4.81,4.18,6.06Zm-.93-7.53c.6,0,1.14,.5,1.26,1.17,.08,.48,.5,.83,.98,.83s.9-.35,.98-.83c.12-.67,.67-1.17,1.27-1.17,.69,0,1.25,.66,1.25,1.48,0,1.06-1.35,2.83-3.43,4.5-.04,.03-.1,.03-.14,0-2.08-1.67-3.43-3.44-3.43-4.5,0-.81,.56-1.48,1.25-1.48Z"/></svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -1 +1,19 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1747121290756" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="51598" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M829.888 739.392L547.84 457.28 706.112 364.8l-512-170.624L364.8 706.112l92.48-158.336 282.112 282.112z" p-id="51599"></path></svg>
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||
width="64.000000pt" height="64.000000pt" viewBox="0 0 64.000000 64.000000"
|
||||
preserveAspectRatio="xMidYMid meet">
|
||||
|
||||
<g transform="translate(0.000000,64.000000) scale(0.100000,-0.100000)"
|
||||
fill="#000000" stroke="none">
|
||||
<path d="M256 561 c-50 -51 -53 -71 -10 -71 23 0 24 -3 24 -60 l0 -60 -60 0
|
||||
c-57 0 -60 1 -60 24 0 14 -5 28 -11 32 -14 8 -109 -84 -109 -106 0 -22 95
|
||||
-114 109 -106 6 4 11 18 11 32 0 23 3 24 60 24 l60 0 0 -60 c0 -57 -1 -60 -24
|
||||
-60 -14 0 -28 -5 -32 -11 -8 -14 84 -109 106 -109 22 0 114 95 106 109 -4 6
|
||||
-18 11 -32 11 -23 0 -24 3 -24 60 l0 60 60 0 c57 0 60 -1 60 -24 0 -14 5 -28
|
||||
11 -32 14 -8 109 84 109 106 0 22 -95 114 -109 106 -6 -4 -11 -18 -11 -32 0
|
||||
-23 -3 -24 -60 -24 l-60 0 0 60 c0 57 1 60 24 60 14 0 28 5 32 11 8 14 -84
|
||||
109 -106 109 -9 0 -37 -22 -64 -49z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 465 B After Width: | Height: | Size: 989 B |
12
src/assets/icons/DetailCompare.svg
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" ?>
|
||||
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
|
||||
<g clip-path="url(#clip0_105_1836)">
|
||||
|
||||
<path d="M13 3.99976H6C4.89543 3.99976 4 4.89519 4 5.99976V17.9998C4 19.1043 4.89543 19.9998 6 19.9998H13M17 3.99976H18C19.1046 3.99976 20 4.89519 20 5.99976V6.99976M20 16.9998V17.9998C20 19.1043 19.1046 19.9998 18 19.9998H17M20 10.9998V12.9998M12 1.99976V21.9998" stroke="#292929" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
|
||||
|
||||
</g>
|
||||
|
||||
<defs>
|
||||
|
After Width: | Height: | Size: 752 B |
22
src/assets/icons/Folder.svg
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||
width="288.000000pt" height="288.000000pt" viewBox="0 0 288.000000 288.000000"
|
||||
preserveAspectRatio="xMidYMid meet">
|
||||
|
||||
<g transform="translate(0.000000,288.000000) scale(0.100000,-0.100000)"
|
||||
fill="#000000" stroke="none">
|
||||
<path d="M379 2446 c-101 -36 -179 -116 -209 -214 -19 -62 -20 -93 -20 -792 0
|
||||
-701 1 -730 20 -793 26 -83 88 -155 168 -194 l57 -28 1045 0 1045 0 47 22
|
||||
c101 46 170 138 188 250 6 32 10 329 10 668 0 659 -3 692 -54 774 -35 54 -101
|
||||
108 -163 131 -52 19 -78 20 -626 20 l-572 0 -46 53 c-25 29 -70 66 -100 82
|
||||
l-54 30 -350 2 c-269 2 -358 0 -386 -11z m710 -175 c20 -11 42 -25 48 -33 6
|
||||
-7 48 -92 92 -188 85 -183 118 -229 196 -274 73 -43 119 -46 635 -46 l490 0 0
|
||||
-517 c0 -496 -1 -519 -20 -547 -10 -17 -36 -40 -57 -53 l-38 -23 -993 0 c-968
|
||||
0 -994 0 -1031 20 -22 11 -48 35 -60 53 -21 34 -21 40 -21 777 0 737 0 743 21
|
||||
777 12 18 37 42 57 53 34 18 60 19 340 20 280 0 306 -1 341 -19z m1381 -174
|
||||
c53 -28 80 -75 80 -139 l0 -48 -506 0 c-498 0 -507 0 -541 21 -31 19 -74 88
|
||||
-103 165 l-10 24 519 0 518 0 43 -23z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
60
src/assets/icons/editFrontBack.svg
Normal file
@@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||
width="405.000000pt" height="405.000000pt" viewBox="0 0 405.000000 405.000000"
|
||||
preserveAspectRatio="xMidYMid meet">
|
||||
|
||||
<g transform="translate(0.000000,405.000000) scale(0.100000,-0.100000)"
|
||||
fill="#000000" stroke="none">
|
||||
<path d="M1385 3584 c-343 -47 -677 -124 -939 -214 -180 -62 -244 -94 -252
|
||||
-124 -4 -18 13 -77 60 -203 36 -98 96 -263 134 -368 60 -168 71 -191 94 -199
|
||||
20 -7 66 2 210 42 100 29 186 52 191 52 4 0 7 -485 7 -1078 0 -1033 1 -1080
|
||||
18 -1095 17 -16 109 -17 1119 -17 1050 0 1101 1 1116 18 15 16 17 66 19 447
|
||||
l3 429 119 36 c124 37 156 59 156 105 0 44 -33 67 -156 109 l-119 41 -3 503
|
||||
c-1 345 1 502 8 502 6 0 92 -23 191 -52 143 -41 186 -49 207 -42 24 8 34 29
|
||||
89 184 34 96 94 262 134 368 50 137 69 200 65 218 -8 30 -72 62 -252 124 -271
|
||||
94 -596 167 -947 215 -179 24 -208 25 -645 24 -423 -1 -470 -3 -627 -25z
|
||||
m1009 -131 c-12 -51 -55 -125 -100 -173 -141 -151 -397 -151 -538 0 -45 48
|
||||
-88 122 -100 173 l-6 27 375 0 375 0 -6 -27z m-860 -25 c26 -163 199 -336 376
|
||||
-377 110 -26 254 -6 354 47 116 62 233 215 252 330 8 50 3 49 166 26 294 -40
|
||||
599 -110 853 -195 83 -27 157 -54 165 -59 13 -8 11 -20 -13 -87 -16 -43 -63
|
||||
-172 -104 -288 -42 -115 -77 -211 -78 -213 -2 -2 -90 22 -196 53 -107 30 -202
|
||||
55 -213 55 -11 0 -28 -7 -38 -17 -17 -15 -18 -46 -18 -555 0 -296 -3 -538 -8
|
||||
-538 -4 0 -72 22 -150 48 -142 47 -143 48 -123 66 18 17 21 31 21 109 0 101
|
||||
-12 127 -60 127 -50 0 -62 -27 -58 -134 2 -53 3 -96 2 -96 0 0 -40 13 -89 30
|
||||
-100 34 -131 37 -162 15 -37 -26 -35 -54 17 -211 28 -81 50 -154 50 -161 0 -7
|
||||
-10 -13 -22 -13 -50 0 -76 -63 -41 -102 11 -13 30 -18 64 -18 l48 0 81 -250
|
||||
c85 -263 95 -280 151 -280 53 0 67 24 130 235 50 168 65 204 90 228 60 56 59
|
||||
63 59 -333 l0 -360 -1015 0 -1015 0 0 1087 c0 997 -1 1088 -17 1105 -9 10 -26
|
||||
18 -37 18 -12 0 -108 -25 -215 -55 -106 -31 -194 -55 -196 -53 -1 2 -36 98
|
||||
-78 213 -41 116 -88 245 -104 288 -24 67 -26 79 -13 87 30 19 318 110 455 144
|
||||
235 59 586 123 686 125 35 1 37 0 43 -41z"/>
|
||||
<path d="M1410 2700 c-25 -25 -25 -51 -1 -81 16 -19 30 -24 90 -27 110 -6 151
|
||||
12 151 67 0 49 -26 61 -128 61 -79 0 -95 -3 -112 -20z"/>
|
||||
<path d="M1747 2702 c-21 -23 -22 -66 -1 -86 22 -23 55 -29 135 -24 60 3 74 8
|
||||
90 27 24 30 24 56 -1 81 -17 17 -33 20 -113 20 -78 0 -97 -3 -110 -18z"/>
|
||||
<path d="M2080 2700 c-25 -25 -25 -51 -1 -81 16 -19 30 -24 90 -27 110 -6 151
|
||||
12 151 67 0 49 -26 61 -128 61 -79 0 -95 -3 -112 -20z"/>
|
||||
<path d="M2417 2702 c-21 -23 -22 -66 -1 -86 22 -23 55 -29 135 -24 60 3 74 8
|
||||
90 27 24 30 24 56 -1 81 -17 17 -33 20 -113 20 -78 0 -97 -3 -110 -18z"/>
|
||||
<path d="M1286 2574 c-12 -12 -16 -37 -16 -109 0 -86 2 -95 22 -109 30 -21 54
|
||||
-20 78 4 17 17 20 33 20 108 0 73 -3 92 -18 105 -23 21 -66 22 -86 1z"/>
|
||||
<path d="M2677 2572 c-13 -14 -17 -39 -17 -105 0 -74 3 -90 20 -107 24 -24 48
|
||||
-25 78 -4 20 14 22 23 22 109 0 72 -4 97 -16 109 -21 22 -67 20 -87 -2z"/>
|
||||
<path d="M1292 2264 c-20 -14 -22 -23 -22 -109 0 -104 10 -125 59 -125 48 0
|
||||
61 26 61 123 0 74 -3 90 -20 107 -24 24 -48 25 -78 4z"/>
|
||||
<path d="M2680 2260 c-17 -17 -20 -33 -20 -108 0 -98 12 -122 63 -122 47 0 57
|
||||
22 57 125 0 86 -2 95 -22 109 -30 21 -54 20 -78 -4z"/>
|
||||
<path d="M1287 1942 c-26 -28 -24 -192 1 -215 24 -22 65 -21 85 1 26 28 24
|
||||
192 -1 215 -24 22 -65 21 -85 -1z"/>
|
||||
<path d="M1310 1643 c-32 -11 -40 -37 -40 -129 0 -85 2 -94 22 -108 30 -21 54
|
||||
-20 78 4 17 17 20 33 20 109 0 85 -1 91 -26 110 -28 22 -30 23 -54 14z"/>
|
||||
<path d="M1410 1370 c-24 -24 -25 -48 -4 -78 14 -20 23 -22 113 -22 108 0 131
|
||||
11 131 62 0 46 -27 58 -128 58 -79 0 -95 -3 -112 -20z"/>
|
||||
<path d="M1747 1372 c-22 -24 -21 -65 1 -85 15 -13 39 -17 115 -17 88 0 97 2
|
||||
111 22 21 30 20 54 -4 78 -17 17 -33 20 -113 20 -78 0 -97 -3 -110 -18z"/>
|
||||
<path d="M2080 1370 c-24 -24 -25 -48 -4 -78 14 -20 23 -22 113 -22 108 0 131
|
||||
11 131 62 0 46 -27 58 -128 58 -79 0 -95 -3 -112 -20z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.8 KiB |
BIN
src/assets/images/icon/library.png
Normal file
|
After Width: | Height: | Size: 632 B |
BIN
src/assets/images/icon/selected.png
Normal file
|
After Width: | Height: | Size: 582 B |
BIN
src/assets/images/icon/upload_black.png
Normal file
|
After Width: | Height: | Size: 400 B |
BIN
src/assets/images/icon/upload_gray.png
Normal file
|
After Width: | Height: | Size: 355 B |
@@ -62,6 +62,9 @@ li {
|
||||
height: 100%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.ant-dropdown-menu {
|
||||
border-radius: 1rem;
|
||||
}
|
||||
.button_second {
|
||||
width: 14rem;
|
||||
text-align: center;
|
||||
@@ -237,7 +240,7 @@ li {
|
||||
color: #fff;
|
||||
background-color: #000;
|
||||
text-align: center;
|
||||
font-weight: 600;
|
||||
font-weight: 500;
|
||||
border: 2px solid #000;
|
||||
cursor: pointer;
|
||||
box-sizing: border-box;
|
||||
@@ -2106,7 +2109,7 @@ textarea:focus {
|
||||
.generalMenu_printModel_upload .input_border .input_box_btnBox .upload_item .upload_file_item,
|
||||
.generate .input_border .input_box_btnBox .upload_item .upload_file_item {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
left: 1rem;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
height: 4.7rem;
|
||||
@@ -2207,7 +2210,7 @@ textarea:focus {
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
position: relative;
|
||||
width: 4rem;
|
||||
width: 3rem;
|
||||
display: flex;
|
||||
min-height: 3rem;
|
||||
justify-content: center;
|
||||
|
||||
@@ -63,6 +63,9 @@ input:focus{
|
||||
height: 100%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.ant-dropdown-menu{
|
||||
border-radius: 1rem;
|
||||
}
|
||||
.button_second{
|
||||
width: 14rem;
|
||||
text-align: center;
|
||||
@@ -241,7 +244,7 @@ input:focus{
|
||||
color: #fff;
|
||||
background-color: #000;
|
||||
text-align: center;
|
||||
font-weight: 600;
|
||||
font-weight: 500;
|
||||
border: 2px solid #000;
|
||||
cursor: pointer;
|
||||
box-sizing: border-box;
|
||||
@@ -2105,7 +2108,7 @@ textarea:focus{
|
||||
width: 4.7rem;
|
||||
.upload_file_item{
|
||||
position: absolute;
|
||||
left: 0;
|
||||
left: 1rem;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
height: 4.7rem;
|
||||
@@ -2150,7 +2153,7 @@ textarea:focus{
|
||||
cursor: pointer;
|
||||
transition: all .3s;
|
||||
position: relative;
|
||||
width: 4rem;
|
||||
width: 3rem;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 1.2 MiB |
|
Before Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 2.9 MiB |
|
Before Width: | Height: | Size: 987 KiB |
|
Before Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 588 KiB |
|
Before Width: | Height: | Size: 1.2 MiB |
|
Before Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 127 KiB |
|
Before Width: | Height: | Size: 57 KiB |
|
Before Width: | Height: | Size: 801 KiB |
|
Before Width: | Height: | Size: 2.1 MiB |
|
Before Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 223 KiB |
|
Before Width: | Height: | Size: 288 KiB |
|
Before Width: | Height: | Size: 206 KiB |
|
Before Width: | Height: | Size: 88 KiB |
@@ -111,28 +111,46 @@ export default defineComponent({
|
||||
.catch((res) => {accountHomeData.loadingShow = false});
|
||||
}
|
||||
const ungroupWeiXinModel = ()=>{
|
||||
Https.axiosGet(Https.httpUrls.unbindWeChat,).then((rv)=>{
|
||||
message.success(t('frontPage.jsContent1'));
|
||||
let value = {
|
||||
accountExtendList:{
|
||||
WeChat:undefined,
|
||||
Google:accountHomeData.userDetail.accountExtendList?.Google
|
||||
}
|
||||
Modal.confirm({
|
||||
title: t('frontPage.UnbindTip'),
|
||||
okText: t('Yes'),
|
||||
cancelText: t('No'),
|
||||
mask:false,
|
||||
centered:true,
|
||||
onOk() {
|
||||
Https.axiosGet(Https.httpUrls.unbindWeChat,).then((rv)=>{
|
||||
message.success(t('frontPage.jsContent1'));
|
||||
let value = {
|
||||
accountExtendList:{
|
||||
WeChat:undefined,
|
||||
Google:accountHomeData.userDetail.accountExtendList?.Google
|
||||
}
|
||||
}
|
||||
store.commit("upUserDetail", value)
|
||||
})
|
||||
}
|
||||
store.commit("upUserDetail", value)
|
||||
})
|
||||
});
|
||||
}
|
||||
const ungroupGoogleModel = ()=>{
|
||||
Https.axiosGet(Https.httpUrls.unbindGoogle,).then((rv)=>{
|
||||
let value = {
|
||||
accountExtendList:{
|
||||
WeChat:accountHomeData.userDetail.accountExtendList?.WeChat,
|
||||
Google:undefined,
|
||||
}
|
||||
Modal.confirm({
|
||||
title: t('frontPage.UnbindTip'),
|
||||
okText: t('Yes'),
|
||||
cancelText: t('No'),
|
||||
mask:false,
|
||||
centered:true,
|
||||
onOk() {
|
||||
Https.axiosGet(Https.httpUrls.unbindGoogle,).then((rv)=>{
|
||||
let value = {
|
||||
accountExtendList:{
|
||||
WeChat:accountHomeData.userDetail.accountExtendList?.WeChat,
|
||||
Google:undefined,
|
||||
}
|
||||
}
|
||||
store.commit("upUserDetail", value)
|
||||
message.success(t('frontPage.jsContent1'));
|
||||
})
|
||||
}
|
||||
store.commit("upUserDetail", value)
|
||||
message.success(t('frontPage.jsContent1'));
|
||||
})
|
||||
});
|
||||
}
|
||||
const modifyEmail = ()=>{
|
||||
bindPageDom.bindEmail.init('Modify')
|
||||
|
||||
@@ -117,13 +117,12 @@ export default defineComponent({
|
||||
let value = {
|
||||
country:accountHomeData.Country,
|
||||
title:accountHomeData.selectSex,
|
||||
userName:accountHomeData.editUserName,
|
||||
surname:accountHomeData.surname,
|
||||
givenName:accountHomeData.givenName,
|
||||
}
|
||||
store.commit('upUserDetail',value)
|
||||
accountHomeData.loadingShow = false
|
||||
message.success(t('exportModel.jsContent7'))
|
||||
message.success(t('account.jsContent13'))
|
||||
}).catch((err:any)=>{
|
||||
accountHomeData.loadingShow = false
|
||||
})
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
<template>
|
||||
<div class="test_cli admin_page">
|
||||
<div class="test_cli admin_page">
|
||||
<div class="admin_table_search">
|
||||
<div class="admin_state">
|
||||
|
||||
<div class="admin_state_item">
|
||||
<span>{{ $t('admin.StartDate') }}:</span>
|
||||
<span>{{ $t("admin.StartDate") }}:</span>
|
||||
<a-range-picker
|
||||
style="width:250px"
|
||||
style="width: 250px"
|
||||
class="range_picker"
|
||||
v-model:value="rangePickerValue"
|
||||
:placeholder="[
|
||||
@@ -23,35 +22,56 @@
|
||||
</a-range-picker>
|
||||
</div>
|
||||
<div class="admin_state_item">
|
||||
<span>{{ $t('admin.StartTime') }}:</span>
|
||||
<a-time-range-picker style="width:250px" :placeholder="[$t('admin.startTime'), $t('admin.endTime'),]" class="range_picker" valueFormat="HH:mm:ss" v-model:value="rangeTimeValue" />
|
||||
<span>{{ $t("admin.StartTime") }}:</span>
|
||||
<a-time-range-picker
|
||||
style="width: 250px"
|
||||
:placeholder="[
|
||||
$t('admin.startTime'),
|
||||
$t('admin.endTime'),
|
||||
]"
|
||||
class="range_picker"
|
||||
valueFormat="HH:mm:ss"
|
||||
v-model:value="rangeTimeValue"
|
||||
/>
|
||||
</div>
|
||||
<div class="admin_state_item">
|
||||
<span>{{ $t('admin.Email') }}:</span>
|
||||
<input
|
||||
v-model="email"
|
||||
:placeholder="$t('admin.enterEmail')"
|
||||
@keydown.enter="gettrialList"
|
||||
type="text"
|
||||
style="width: 250px"
|
||||
/>
|
||||
</div>
|
||||
<span>{{ $t("admin.Email") }}:</span>
|
||||
<input
|
||||
v-model="email"
|
||||
:placeholder="$t('admin.enterEmail')"
|
||||
@keydown.enter="gettrialList"
|
||||
type="text"
|
||||
style="width: 250px"
|
||||
/>
|
||||
</div>
|
||||
<div class="admin_state_item">
|
||||
<span>{{ $t('admin.UserName') }}:</span>
|
||||
<a-select
|
||||
v-model:value="ids"
|
||||
mode="multiple"
|
||||
style="width: 250px"
|
||||
:filter-option="filterOption"
|
||||
:placeholder="$t('admin.selectUserName')"
|
||||
max-tag-count="responsive"
|
||||
:options="allUserList"
|
||||
@keydown.enter="gettrialList"
|
||||
></a-select>
|
||||
</div>
|
||||
<span>{{ $t("admin.UserName") }}:</span>
|
||||
<a-select
|
||||
v-model:value="ids"
|
||||
mode="multiple"
|
||||
style="width: 250px"
|
||||
:filter-option="filterOption"
|
||||
:placeholder="$t('admin.selectUserName')"
|
||||
max-tag-count="responsive"
|
||||
:options="allUserList"
|
||||
@keydown.enter="gettrialList"
|
||||
></a-select>
|
||||
</div>
|
||||
<div class="admin_state_item">
|
||||
<span>Organization Name:</span>
|
||||
<input
|
||||
v-model="organizationName"
|
||||
placeholder="Please enter Organization Name"
|
||||
@keydown.enter="gettrialList"
|
||||
type="text"
|
||||
style="width: 250px"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="admin_search">
|
||||
<div class="admin_search_item" @click="searchHistoryList">{{ $t('admin.search') }}</div>
|
||||
<div class="admin_search_item" @click="searchHistoryList">
|
||||
{{ $t("admin.search") }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -73,205 +93,207 @@
|
||||
>
|
||||
</a-table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref, createVNode, computed } from "vue";
|
||||
import { useStore } from "vuex";
|
||||
import { Https } from "@/tool/https";
|
||||
import { useI18n } from 'vue-i18n'
|
||||
export default defineComponent({
|
||||
components: {
|
||||
},
|
||||
setup() {
|
||||
const store:any = useStore()
|
||||
let rangePickerValue: any = ref([]);
|
||||
let rangeTimeValue: any = ref([]);
|
||||
let renameData: any = ref({}); //修改名字选中的数据
|
||||
const {t} = useI18n()
|
||||
const columns: any = computed(() => {
|
||||
return [
|
||||
{
|
||||
title: t('admin.Email'),
|
||||
align: "center",
|
||||
dataIndex: "userEmail",
|
||||
key: "userEmail",
|
||||
width:200,
|
||||
fixed: "left",
|
||||
},
|
||||
{
|
||||
title: t('admin.UserId'),
|
||||
align: "center",
|
||||
ellipsis: true,
|
||||
dataIndex: "accountId",
|
||||
key: "accountId",
|
||||
width:100,
|
||||
},
|
||||
{
|
||||
title: t('admin.UserName'),
|
||||
align: "center",
|
||||
ellipsis: 200,
|
||||
dataIndex: "userName",
|
||||
key: "userName",
|
||||
width:100,
|
||||
// customRender: (record: any) => {
|
||||
// let time = formatTime(
|
||||
// record.text / 1000,
|
||||
// "YYYY-MM-DD hh:mm:ss"
|
||||
// );
|
||||
// return time;
|
||||
// },
|
||||
},
|
||||
{
|
||||
title: t('admin.Frequency'),
|
||||
align: "center",
|
||||
ellipsis: true,
|
||||
dataIndex: "designTimes",
|
||||
key: "designTimes",
|
||||
width:100,
|
||||
},
|
||||
{
|
||||
title: t('admin.CreateTime'),
|
||||
align: "center",
|
||||
ellipsis: true,
|
||||
// width: 150,
|
||||
// minWidth: 100,
|
||||
// maxWidth: 200,
|
||||
// resizable: true,
|
||||
dataIndex: "createTime",
|
||||
key: "createTime",
|
||||
width:200,
|
||||
},
|
||||
{
|
||||
title: t('admin.Credits'),
|
||||
align: "center",
|
||||
ellipsis: true,
|
||||
// width: 150,
|
||||
// minWidth: 100,
|
||||
// maxWidth: 200,
|
||||
// resizable: true,
|
||||
dataIndex: "credits",
|
||||
key: "credits",
|
||||
width:100,
|
||||
},
|
||||
];
|
||||
});
|
||||
import { defineComponent, ref, createVNode, computed } from "vue";
|
||||
import { useStore } from "vuex";
|
||||
import { Https } from "@/tool/https";
|
||||
import { useI18n } from "vue-i18n";
|
||||
export default defineComponent({
|
||||
components: {},
|
||||
setup() {
|
||||
const store: any = useStore();
|
||||
let rangePickerValue: any = ref([]);
|
||||
let rangeTimeValue: any = ref([]);
|
||||
let renameData: any = ref({}); //修改名字选中的数据
|
||||
const { t } = useI18n();
|
||||
const columns: any = computed(() => {
|
||||
return [
|
||||
{
|
||||
title: t("admin.Email"),
|
||||
align: "center",
|
||||
dataIndex: "userEmail",
|
||||
key: "userEmail",
|
||||
width: 200,
|
||||
fixed: "left",
|
||||
},
|
||||
{
|
||||
title: t("admin.UserId"),
|
||||
align: "center",
|
||||
ellipsis: true,
|
||||
dataIndex: "accountId",
|
||||
key: "accountId",
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: t("admin.UserName"),
|
||||
align: "center",
|
||||
ellipsis: 200,
|
||||
dataIndex: "userName",
|
||||
key: "userName",
|
||||
width: 100,
|
||||
// customRender: (record: any) => {
|
||||
// let time = formatTime(
|
||||
// record.text / 1000,
|
||||
// "YYYY-MM-DD hh:mm:ss"
|
||||
// );
|
||||
// return time;
|
||||
// },
|
||||
},
|
||||
{
|
||||
title: t("admin.Frequency"),
|
||||
align: "center",
|
||||
ellipsis: true,
|
||||
dataIndex: "designTimes",
|
||||
key: "designTimes",
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: t("admin.CreateTime"),
|
||||
align: "center",
|
||||
ellipsis: true,
|
||||
// width: 150,
|
||||
// minWidth: 100,
|
||||
// maxWidth: 200,
|
||||
// resizable: true,
|
||||
dataIndex: "createTime",
|
||||
key: "createTime",
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: t("admin.Credits"),
|
||||
align: "center",
|
||||
ellipsis: true,
|
||||
// width: 150,
|
||||
// minWidth: 100,
|
||||
// maxWidth: 200,
|
||||
// resizable: true,
|
||||
dataIndex: "credits",
|
||||
key: "credits",
|
||||
width: 100,
|
||||
},
|
||||
];
|
||||
});
|
||||
|
||||
let allUserList: any = computed(()=>{
|
||||
return store.state.adminPage.allUserList
|
||||
})
|
||||
let ids = ref([])
|
||||
let email = ref('')
|
||||
let dataList: any = ref([]);
|
||||
let status: any = ref(0);
|
||||
let filterOption = (input: any, option: any) => {
|
||||
// 使用 option.label 进行搜索
|
||||
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0;
|
||||
};
|
||||
return {
|
||||
rangePickerValue,
|
||||
rangeTimeValue,
|
||||
columns,
|
||||
dataList,
|
||||
allUserList,
|
||||
ids,
|
||||
email,
|
||||
renameData,
|
||||
status,
|
||||
filterOption,
|
||||
};
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentPage: 1,
|
||||
pageSize: 10,
|
||||
total: 0,
|
||||
historyTableHeight: 0,
|
||||
handleResizeColumn: (w:any, col:any) => {
|
||||
col.width = w;
|
||||
let allUserList: any = computed(() => {
|
||||
return store.state.adminPage.allUserList;
|
||||
});
|
||||
let ids = ref([]);
|
||||
let email = ref("");
|
||||
let dataList: any = ref([]);
|
||||
let status: any = ref(0);
|
||||
let organizationName: any = ref("");
|
||||
let filterOption = (input: any, option: any) => {
|
||||
// 使用 option.label 进行搜索
|
||||
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0;
|
||||
};
|
||||
return {
|
||||
rangePickerValue,
|
||||
rangeTimeValue,
|
||||
columns,
|
||||
dataList,
|
||||
allUserList,
|
||||
ids,
|
||||
email,
|
||||
renameData,
|
||||
status,
|
||||
filterOption,
|
||||
organizationName,
|
||||
};
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentPage: 1,
|
||||
pageSize: 10,
|
||||
total: 0,
|
||||
historyTableHeight: 0,
|
||||
handleResizeColumn: (w: any, col: any) => {
|
||||
col.width = w;
|
||||
},
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
let historyTable: any = this.$refs.historyTable;
|
||||
this.historyTableHeight = historyTable.clientHeight - 200;
|
||||
this.gettrialList();
|
||||
},
|
||||
methods: {
|
||||
//改变页码
|
||||
changePage(e: any) {
|
||||
this.currentPage = e.current;
|
||||
this.pageSize = e.pageSize;
|
||||
this.gettrialList();
|
||||
},
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
let historyTable: any = this.$refs.historyTable;
|
||||
this.historyTableHeight = historyTable.clientHeight - 200;
|
||||
this.gettrialList();
|
||||
},
|
||||
methods: {
|
||||
//改变页码
|
||||
changePage(e: any) {
|
||||
this.currentPage = e.current;
|
||||
this.pageSize = e.pageSize;
|
||||
this.gettrialList();
|
||||
},
|
||||
|
||||
//查询列表
|
||||
searchHistoryList() {
|
||||
this.currentPage = 1;
|
||||
this.gettrialList();
|
||||
},
|
||||
//查询列表
|
||||
searchHistoryList() {
|
||||
this.currentPage = 1;
|
||||
this.gettrialList();
|
||||
},
|
||||
|
||||
//获取列表
|
||||
gettrialList() {
|
||||
let startTime: any = this.rangeTimeValue?.[0]
|
||||
? this.rangeTimeValue[0]
|
||||
: '00:00:00';
|
||||
let endTime: any = this.rangeTimeValue?.[1]
|
||||
? this.rangeTimeValue[1]
|
||||
: '23:59:59';
|
||||
let startDate: any = this.rangePickerValue?.[0]
|
||||
? this.rangePickerValue[0]+' '+startTime
|
||||
: "";
|
||||
let endDate: any = this.rangePickerValue?.[1]
|
||||
? this.rangePickerValue[1]+' '+endTime
|
||||
: "";
|
||||
let ids = this.ids.join(',')
|
||||
let data = {
|
||||
endTime:endDate,
|
||||
startTime:startDate,
|
||||
ids:ids,
|
||||
email:this.email.trim(),
|
||||
}
|
||||
Https.axiosGet(Https.httpUrls.getDesignStatistic,{params:data}).then((rv: any) => {
|
||||
if (rv) {
|
||||
this.dataList = rv
|
||||
// this.workspaceItem.position = this.singleTypeList[0].label
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
//删除分组
|
||||
// deleteGroup(record: any, index: number) {
|
||||
// let deleteGroupFun = (id: any, index: number) => {
|
||||
// let data = {
|
||||
// userGroupId: id,
|
||||
// };
|
||||
// Https.axiosPost(Https.httpUrls.deleteUserGroup, data).then(
|
||||
// (rv: any) => {
|
||||
// this.dataList.splice(index, 1);
|
||||
// }
|
||||
// );
|
||||
// };
|
||||
// Modal.confirm({
|
||||
// title: "",
|
||||
// icon: createVNode(ExclamationCircleOutlined),
|
||||
// okText: "Yes",
|
||||
// cancelText: "No",
|
||||
// centered: true,
|
||||
// mask: false,
|
||||
// onOk() {
|
||||
// deleteGroupFun(record.id, index);
|
||||
// },
|
||||
// });
|
||||
// },
|
||||
|
||||
|
||||
},
|
||||
});
|
||||
//获取列表
|
||||
gettrialList() {
|
||||
let startTime: any = this.rangeTimeValue?.[0]
|
||||
? this.rangeTimeValue[0]
|
||||
: "00:00:00";
|
||||
let endTime: any = this.rangeTimeValue?.[1]
|
||||
? this.rangeTimeValue[1]
|
||||
: "23:59:59";
|
||||
let startDate: any = this.rangePickerValue?.[0]
|
||||
? this.rangePickerValue[0] + " " + startTime
|
||||
: "";
|
||||
let endDate: any = this.rangePickerValue?.[1]
|
||||
? this.rangePickerValue[1] + " " + endTime
|
||||
: "";
|
||||
let ids = this.ids.join(",");
|
||||
let data = {
|
||||
endTime: endDate,
|
||||
startTime: startDate,
|
||||
ids: ids,
|
||||
email: this.email.trim(),
|
||||
organizationName: this.organizationName,
|
||||
};
|
||||
Https.axiosGet(Https.httpUrls.getDesignStatistic, {
|
||||
params: data,
|
||||
}).then((rv: any) => {
|
||||
if (rv) {
|
||||
this.dataList = rv;
|
||||
// this.workspaceItem.position = this.singleTypeList[0].label
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
//删除分组
|
||||
// deleteGroup(record: any, index: number) {
|
||||
// let deleteGroupFun = (id: any, index: number) => {
|
||||
// let data = {
|
||||
// userGroupId: id,
|
||||
// };
|
||||
// Https.axiosPost(Https.httpUrls.deleteUserGroup, data).then(
|
||||
// (rv: any) => {
|
||||
// this.dataList.splice(index, 1);
|
||||
// }
|
||||
// );
|
||||
// };
|
||||
// Modal.confirm({
|
||||
// title: "",
|
||||
// icon: createVNode(ExclamationCircleOutlined),
|
||||
// okText: "Yes",
|
||||
// cancelText: "No",
|
||||
// centered: true,
|
||||
// mask: false,
|
||||
// onOk() {
|
||||
// deleteGroupFun(record.id, index);
|
||||
// },
|
||||
// });
|
||||
// },
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.admin_page .admin_table_search .admin_state {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.admin_page .admin_table_search .admin_state {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
</style>
|
||||
@@ -1,12 +1,11 @@
|
||||
<template>
|
||||
<div class="test_cli admin_page">
|
||||
<div class="test_cli admin_page">
|
||||
<div class="admin_table_search">
|
||||
<div class="admin_state">
|
||||
|
||||
<div class="admin_state_item">
|
||||
<span>Start Date:</span>
|
||||
<a-range-picker
|
||||
style="width:250px"
|
||||
style="width: 250px"
|
||||
class="range_picker"
|
||||
v-model:value="rangePickerValue"
|
||||
:placeholder="[
|
||||
@@ -24,34 +23,51 @@
|
||||
</div>
|
||||
<div class="admin_state_item">
|
||||
<span>Start Time:</span>
|
||||
<a-time-range-picker style="width:250px" class="range_picker" valueFormat="HH:mm:ss" v-model:value="rangeTimeValue" />
|
||||
<a-time-range-picker
|
||||
style="width: 250px"
|
||||
class="range_picker"
|
||||
valueFormat="HH:mm:ss"
|
||||
v-model:value="rangeTimeValue"
|
||||
/>
|
||||
</div>
|
||||
<div class="admin_state_item">
|
||||
<span>Email:</span>
|
||||
<input
|
||||
v-model="email"
|
||||
placeholder="Please enter email"
|
||||
@keydown.enter="gettrialList"
|
||||
type="text"
|
||||
style="width: 250px"
|
||||
/>
|
||||
</div>
|
||||
<span>Email:</span>
|
||||
<input
|
||||
v-model="email"
|
||||
placeholder="Please enter email"
|
||||
@keydown.enter="gettrialList"
|
||||
type="text"
|
||||
style="width: 250px"
|
||||
/>
|
||||
</div>
|
||||
<div class="admin_state_item">
|
||||
<span>User Name:</span>
|
||||
<a-select
|
||||
v-model:value="ids"
|
||||
mode="multiple"
|
||||
style="width: 250px"
|
||||
:filter-option="filterOption"
|
||||
placeholder="Select Item..."
|
||||
max-tag-count="responsive"
|
||||
:options="allUserList"
|
||||
@keydown.enter="gettrialList"
|
||||
></a-select>
|
||||
</div>
|
||||
<span>User Name:</span>
|
||||
<a-select
|
||||
v-model:value="ids"
|
||||
mode="multiple"
|
||||
style="width: 250px"
|
||||
:filter-option="filterOption"
|
||||
placeholder="Select Item..."
|
||||
max-tag-count="responsive"
|
||||
:options="allUserList"
|
||||
@keydown.enter="gettrialList"
|
||||
></a-select>
|
||||
</div>
|
||||
<div class="admin_state_item">
|
||||
<span>Organization Name:</span>
|
||||
<input
|
||||
v-model="organizationName"
|
||||
placeholder="Please enter Organization Name"
|
||||
@keydown.enter="gettrialList"
|
||||
type="text"
|
||||
style="width: 250px"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="admin_search">
|
||||
<div class="admin_search_item" @click="searchHistoryList">Search</div>
|
||||
<div class="admin_search_item" @click="searchHistoryList">
|
||||
Search
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -73,270 +89,272 @@
|
||||
>
|
||||
</a-table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref, createVNode, computed } from "vue";
|
||||
import { useStore } from "vuex";
|
||||
import { Https } from "@/tool/https";
|
||||
export default defineComponent({
|
||||
components: {
|
||||
},
|
||||
setup() {
|
||||
const store:any = useStore()
|
||||
let rangePickerValue: any = ref([]);
|
||||
let rangeTimeValue: any = ref([]);
|
||||
let renameData: any = ref({}); //修改名字选中的数据
|
||||
const columns: any = computed(() => {
|
||||
return [
|
||||
{
|
||||
title: 'Email',
|
||||
align: "center",
|
||||
dataIndex: "userEmail",
|
||||
key: "userEmail",
|
||||
width:200,
|
||||
fixed: "left",
|
||||
},
|
||||
{
|
||||
title: 'User Id',
|
||||
align: "center",
|
||||
ellipsis: true,
|
||||
dataIndex: "accountId",
|
||||
key: "accountId",
|
||||
width:100,
|
||||
},
|
||||
{
|
||||
title: 'User Name',
|
||||
align: "center",
|
||||
ellipsis: 200,
|
||||
dataIndex: "userName",
|
||||
key: "userName",
|
||||
width:100,
|
||||
// customRender: (record: any) => {
|
||||
// let time = formatTime(
|
||||
// record.text / 1000,
|
||||
// "YYYY-MM-DD hh:mm:ss"
|
||||
// );
|
||||
// return time;
|
||||
// },
|
||||
},
|
||||
{
|
||||
title: 'isTrial',
|
||||
align: "center",
|
||||
ellipsis: true,
|
||||
dataIndex: "isTrial",
|
||||
key: "isTrial",
|
||||
width:100,
|
||||
customRender: (record: any) => {
|
||||
let str
|
||||
if(record.value == 1){
|
||||
str ='Yes'
|
||||
}else{
|
||||
str ='No'
|
||||
}
|
||||
return str;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'Frequency',
|
||||
align: "center",
|
||||
ellipsis: true,
|
||||
dataIndex: "designTimes",
|
||||
key: "designTimes",
|
||||
width:100,
|
||||
},
|
||||
{
|
||||
title: 'Country',
|
||||
align: "center",
|
||||
ellipsis: true,
|
||||
dataIndex: "country",
|
||||
key: "country",
|
||||
width:200,
|
||||
},
|
||||
{
|
||||
title: 'Title',
|
||||
align: "center",
|
||||
ellipsis: true,
|
||||
dataIndex: "title",
|
||||
key: "title",
|
||||
width:100,
|
||||
},
|
||||
{
|
||||
title: 'Surname',
|
||||
align: "center",
|
||||
ellipsis: true,
|
||||
dataIndex: "surname",
|
||||
key: "surname",
|
||||
width:150,
|
||||
},
|
||||
{
|
||||
title: 'Given Name',
|
||||
align: "center",
|
||||
ellipsis: true,
|
||||
dataIndex: "givenName",
|
||||
key: "givenName",
|
||||
width:100,
|
||||
},
|
||||
{
|
||||
title: 'Create Time',
|
||||
align: "center",
|
||||
ellipsis: true,
|
||||
dataIndex: "createTime",
|
||||
key: "createTime",
|
||||
width:200,
|
||||
},
|
||||
{
|
||||
title: 'Credits',
|
||||
align: "center",
|
||||
ellipsis: true,
|
||||
// width: 150,
|
||||
// minWidth: 100,
|
||||
// maxWidth: 200,
|
||||
// resizable: true,
|
||||
dataIndex: "credits",
|
||||
key: "credits",
|
||||
width:100,
|
||||
},
|
||||
{
|
||||
title: 'Occupation',
|
||||
align: "center",
|
||||
ellipsis: true,
|
||||
// width: 150,
|
||||
// minWidth: 100,
|
||||
// maxWidth: 200,
|
||||
// resizable: true,
|
||||
dataIndex: "occupation",
|
||||
key: "occupation",
|
||||
width:100,
|
||||
},
|
||||
{
|
||||
title: 'Trial Order Id',
|
||||
align: "center",
|
||||
ellipsis: true,
|
||||
// width: 150,
|
||||
// resizable: true,
|
||||
dataIndex: "trialOrderId",
|
||||
key: "trialOrderId",
|
||||
width:100,
|
||||
},
|
||||
];
|
||||
});
|
||||
import { defineComponent, ref, createVNode, computed } from "vue";
|
||||
import { useStore } from "vuex";
|
||||
import { Https } from "@/tool/https";
|
||||
export default defineComponent({
|
||||
components: {},
|
||||
setup() {
|
||||
const store: any = useStore();
|
||||
let rangePickerValue: any = ref([]);
|
||||
let rangeTimeValue: any = ref([]);
|
||||
let renameData: any = ref({}); //修改名字选中的数据
|
||||
let organizationName: any = ref("");
|
||||
const columns: any = computed(() => {
|
||||
return [
|
||||
{
|
||||
title: "Email",
|
||||
align: "center",
|
||||
dataIndex: "userEmail",
|
||||
key: "userEmail",
|
||||
width: 200,
|
||||
fixed: "left",
|
||||
},
|
||||
{
|
||||
title: "User Id",
|
||||
align: "center",
|
||||
ellipsis: true,
|
||||
dataIndex: "accountId",
|
||||
key: "accountId",
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: "User Name",
|
||||
align: "center",
|
||||
ellipsis: 200,
|
||||
dataIndex: "userName",
|
||||
key: "userName",
|
||||
width: 100,
|
||||
// customRender: (record: any) => {
|
||||
// let time = formatTime(
|
||||
// record.text / 1000,
|
||||
// "YYYY-MM-DD hh:mm:ss"
|
||||
// );
|
||||
// return time;
|
||||
// },
|
||||
},
|
||||
{
|
||||
title: "isTrial",
|
||||
align: "center",
|
||||
ellipsis: true,
|
||||
dataIndex: "isTrial",
|
||||
key: "isTrial",
|
||||
width: 100,
|
||||
customRender: (record: any) => {
|
||||
let str;
|
||||
if (record.value == 1) {
|
||||
str = "Yes";
|
||||
} else {
|
||||
str = "No";
|
||||
}
|
||||
return str;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "Frequency",
|
||||
align: "center",
|
||||
ellipsis: true,
|
||||
dataIndex: "designTimes",
|
||||
key: "designTimes",
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: "Country",
|
||||
align: "center",
|
||||
ellipsis: true,
|
||||
dataIndex: "country",
|
||||
key: "country",
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: "Title",
|
||||
align: "center",
|
||||
ellipsis: true,
|
||||
dataIndex: "title",
|
||||
key: "title",
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: "Surname",
|
||||
align: "center",
|
||||
ellipsis: true,
|
||||
dataIndex: "surname",
|
||||
key: "surname",
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
title: "Given Name",
|
||||
align: "center",
|
||||
ellipsis: true,
|
||||
dataIndex: "givenName",
|
||||
key: "givenName",
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: "Create Time",
|
||||
align: "center",
|
||||
ellipsis: true,
|
||||
dataIndex: "createTime",
|
||||
key: "createTime",
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: "Credits",
|
||||
align: "center",
|
||||
ellipsis: true,
|
||||
// width: 150,
|
||||
// minWidth: 100,
|
||||
// maxWidth: 200,
|
||||
// resizable: true,
|
||||
dataIndex: "credits",
|
||||
key: "credits",
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: "Occupation",
|
||||
align: "center",
|
||||
ellipsis: true,
|
||||
// width: 150,
|
||||
// minWidth: 100,
|
||||
// maxWidth: 200,
|
||||
// resizable: true,
|
||||
dataIndex: "occupation",
|
||||
key: "occupation",
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: "Trial Order Id",
|
||||
align: "center",
|
||||
ellipsis: true,
|
||||
// width: 150,
|
||||
// resizable: true,
|
||||
dataIndex: "trialOrderId",
|
||||
key: "trialOrderId",
|
||||
width: 100,
|
||||
},
|
||||
];
|
||||
});
|
||||
|
||||
let allUserList: any = computed(()=>{
|
||||
return store.state.adminPage.allUserList
|
||||
})
|
||||
let ids = ref([])
|
||||
let email = ref('')
|
||||
let dataList: any = ref([]);
|
||||
let status: any = ref(0);
|
||||
let filterOption = (input: any, option: any) => {
|
||||
// 使用 option.label 进行搜索
|
||||
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0;
|
||||
};
|
||||
return {
|
||||
rangePickerValue,
|
||||
rangeTimeValue,
|
||||
columns,
|
||||
dataList,
|
||||
allUserList,
|
||||
ids,
|
||||
email,
|
||||
renameData,
|
||||
status,
|
||||
filterOption,
|
||||
};
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentPage: 1,
|
||||
pageSize: 10,
|
||||
total: 0,
|
||||
historyTableHeight: 0,
|
||||
handleResizeColumn: (w:any, col:any) => {
|
||||
col.width = w;
|
||||
let allUserList: any = computed(() => {
|
||||
return store.state.adminPage.allUserList;
|
||||
});
|
||||
let ids = ref([]);
|
||||
let email = ref("");
|
||||
let dataList: any = ref([]);
|
||||
let status: any = ref(0);
|
||||
let filterOption = (input: any, option: any) => {
|
||||
// 使用 option.label 进行搜索
|
||||
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0;
|
||||
};
|
||||
return {
|
||||
rangePickerValue,
|
||||
organizationName,
|
||||
rangeTimeValue,
|
||||
columns,
|
||||
dataList,
|
||||
allUserList,
|
||||
ids,
|
||||
email,
|
||||
renameData,
|
||||
status,
|
||||
filterOption,
|
||||
};
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentPage: 1,
|
||||
pageSize: 10,
|
||||
total: 0,
|
||||
historyTableHeight: 0,
|
||||
handleResizeColumn: (w: any, col: any) => {
|
||||
col.width = w;
|
||||
},
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
let historyTable: any = this.$refs.historyTable;
|
||||
this.historyTableHeight = historyTable.clientHeight - 200;
|
||||
this.gettrialList();
|
||||
},
|
||||
methods: {
|
||||
//改变页码
|
||||
changePage(e: any) {
|
||||
this.currentPage = e.current;
|
||||
this.pageSize = e.pageSize;
|
||||
this.gettrialList();
|
||||
},
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
let historyTable: any = this.$refs.historyTable;
|
||||
this.historyTableHeight = historyTable.clientHeight - 200;
|
||||
this.gettrialList();
|
||||
},
|
||||
methods: {
|
||||
//改变页码
|
||||
changePage(e: any) {
|
||||
this.currentPage = e.current;
|
||||
this.pageSize = e.pageSize;
|
||||
this.gettrialList();
|
||||
},
|
||||
|
||||
//查询列表
|
||||
searchHistoryList() {
|
||||
this.currentPage = 1;
|
||||
this.gettrialList();
|
||||
},
|
||||
//查询列表
|
||||
searchHistoryList() {
|
||||
this.currentPage = 1;
|
||||
this.gettrialList();
|
||||
},
|
||||
|
||||
//获取列表
|
||||
gettrialList() {
|
||||
let startTime: any = this.rangeTimeValue?.[0]
|
||||
? this.rangeTimeValue?.[0]
|
||||
: '00:00:00';
|
||||
let endTime: any = this.rangeTimeValue[1]
|
||||
? this.rangeTimeValue[1]
|
||||
: '23:59:59';
|
||||
let startDate: any = this.rangePickerValue[0]
|
||||
? this.rangePickerValue[0]+' '+startTime
|
||||
: "";
|
||||
let endDate: any = this.rangePickerValue[1]
|
||||
? this.rangePickerValue[1]+' '+endTime
|
||||
: "";
|
||||
let ids = this.ids.join(',')
|
||||
let data = {
|
||||
endTime:endDate,
|
||||
startTime:startDate,
|
||||
ids:ids,
|
||||
email:this.email.trim(),
|
||||
}
|
||||
Https.axiosGet(Https.httpUrls.getDesignStatistic,{params:data}).then((rv: any) => {
|
||||
if (rv) {
|
||||
this.dataList = rv
|
||||
// this.workspaceItem.position = this.singleTypeList[0].label
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
//删除分组
|
||||
// deleteGroup(record: any, index: number) {
|
||||
// let deleteGroupFun = (id: any, index: number) => {
|
||||
// let data = {
|
||||
// userGroupId: id,
|
||||
// };
|
||||
// Https.axiosPost(Https.httpUrls.deleteUserGroup, data).then(
|
||||
// (rv: any) => {
|
||||
// this.dataList.splice(index, 1);
|
||||
// }
|
||||
// );
|
||||
// };
|
||||
// Modal.confirm({
|
||||
// title: "",
|
||||
// icon: createVNode(ExclamationCircleOutlined),
|
||||
// okText: "Yes",
|
||||
// cancelText: "No",
|
||||
// centered: true,
|
||||
// mask: false,
|
||||
// onOk() {
|
||||
// deleteGroupFun(record.id, index);
|
||||
// },
|
||||
// });
|
||||
// },
|
||||
|
||||
|
||||
},
|
||||
});
|
||||
//获取列表
|
||||
gettrialList() {
|
||||
let startTime: any = this.rangeTimeValue?.[0]
|
||||
? this.rangeTimeValue?.[0]
|
||||
: "00:00:00";
|
||||
let endTime: any = this.rangeTimeValue[1]
|
||||
? this.rangeTimeValue[1]
|
||||
: "23:59:59";
|
||||
let startDate: any = this.rangePickerValue[0]
|
||||
? this.rangePickerValue[0] + " " + startTime
|
||||
: "";
|
||||
let endDate: any = this.rangePickerValue[1]
|
||||
? this.rangePickerValue[1] + " " + endTime
|
||||
: "";
|
||||
let ids = this.ids.join(",");
|
||||
let data = {
|
||||
endTime: endDate,
|
||||
startTime: startDate,
|
||||
ids: ids,
|
||||
email: this.email.trim(),
|
||||
organizationName: this.organizationName,
|
||||
};
|
||||
Https.axiosGet(Https.httpUrls.getDesignStatistic, {
|
||||
params: data,
|
||||
}).then((rv: any) => {
|
||||
if (rv) {
|
||||
this.dataList = rv;
|
||||
// this.workspaceItem.position = this.singleTypeList[0].label
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
//删除分组
|
||||
// deleteGroup(record: any, index: number) {
|
||||
// let deleteGroupFun = (id: any, index: number) => {
|
||||
// let data = {
|
||||
// userGroupId: id,
|
||||
// };
|
||||
// Https.axiosPost(Https.httpUrls.deleteUserGroup, data).then(
|
||||
// (rv: any) => {
|
||||
// this.dataList.splice(index, 1);
|
||||
// }
|
||||
// );
|
||||
// };
|
||||
// Modal.confirm({
|
||||
// title: "",
|
||||
// icon: createVNode(ExclamationCircleOutlined),
|
||||
// okText: "Yes",
|
||||
// cancelText: "No",
|
||||
// centered: true,
|
||||
// mask: false,
|
||||
// onOk() {
|
||||
// deleteGroupFun(record.id, index);
|
||||
// },
|
||||
// });
|
||||
// },
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.admin_page .admin_table_search .admin_state {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.admin_page .admin_table_search .admin_state {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
</style>
|
||||
@@ -1,228 +1,305 @@
|
||||
<template>
|
||||
<div class="admin_page">
|
||||
<div class="admin_table_search" >
|
||||
<div class="admin_state">
|
||||
<div class="admin_page">
|
||||
<div class="admin_table_search">
|
||||
<div class="admin_state">
|
||||
<div class="admin_state_item">
|
||||
<span>Status:</span>
|
||||
<a-select
|
||||
v-model:value="status"
|
||||
size="large"
|
||||
style="width: 250px"
|
||||
optionFilterProp="label"
|
||||
:options="statusList"
|
||||
placeholder="Please select"
|
||||
allowClear
|
||||
show-search
|
||||
></a-select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="admin_search">
|
||||
<div class="admin_search_item" @click="searchHistoryList">
|
||||
Search
|
||||
</div>
|
||||
<div class="admin_search_item" @click="addhHistoryList">
|
||||
Add
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="admin_table_content" ref="historyTable">
|
||||
<a-table
|
||||
@resizeColumn="handleResizeColumn"
|
||||
:loading="tableLoading"
|
||||
:columns="columns"
|
||||
:data-source="dataList"
|
||||
:scroll="{ y: historyTableHeight }"
|
||||
@change="changePage"
|
||||
:showSorterTooltip='false'
|
||||
:pagination="{
|
||||
showSizeChanger: true,
|
||||
current: currentPage,
|
||||
pageSize: pageSize,
|
||||
total: total,
|
||||
showQuickJumper: true,
|
||||
bordered: false,
|
||||
}"
|
||||
>
|
||||
</a-table>
|
||||
</div>
|
||||
<span>Create Time:</span>
|
||||
<a-range-picker
|
||||
style="width: 250px"
|
||||
class="range_picker"
|
||||
v-model:value="rangePickerValue"
|
||||
:placeholder="[
|
||||
$t('HistoryPage.StartDate'),
|
||||
$t('HistoryPage.EndDate'),
|
||||
]"
|
||||
valueFormat="YYYY-MM-DD"
|
||||
>
|
||||
<template #suffixIcon>
|
||||
<span
|
||||
class="icon iconfont range_picker_icon icon-rili"
|
||||
></span>
|
||||
</template>
|
||||
</a-range-picker>
|
||||
</div>
|
||||
<div class="admin_state_item">
|
||||
<span>Status:</span>
|
||||
<a-select
|
||||
v-model:value="status"
|
||||
size="large"
|
||||
style="width: 250px"
|
||||
optionFilterProp="label"
|
||||
:options="statusList"
|
||||
placeholder="Please select"
|
||||
@change="changeStatus"
|
||||
allowClear
|
||||
show-search
|
||||
></a-select>
|
||||
</div>
|
||||
<div class="admin_state_item">
|
||||
<span>School:</span>
|
||||
<a-select
|
||||
v-model:value="school"
|
||||
size="large"
|
||||
style="width: 250px"
|
||||
optionFilterProp="label"
|
||||
:options="schoolList"
|
||||
placeholder="Please select"
|
||||
allowClear
|
||||
show-search
|
||||
@focus="handleFocus"
|
||||
></a-select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="admin_search">
|
||||
<div class="admin_search_item" @click="searchHistoryList">
|
||||
Search
|
||||
</div>
|
||||
<div class="admin_search_item" @click="addhHistoryList">
|
||||
Add
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="admin_table_content" ref="historyTable">
|
||||
<a-table
|
||||
@resizeColumn="handleResizeColumn"
|
||||
:loading="tableLoading"
|
||||
:columns="columns"
|
||||
:data-source="dataList"
|
||||
:scroll="{ y: historyTableHeight }"
|
||||
@change="changePage"
|
||||
:showSorterTooltip="false"
|
||||
:pagination="{
|
||||
showSizeChanger: true,
|
||||
current: currentPage,
|
||||
pageSize: pageSize,
|
||||
total: total,
|
||||
showQuickJumper: true,
|
||||
bordered: false,
|
||||
}"
|
||||
>
|
||||
</a-table>
|
||||
</div>
|
||||
<add ref="add" @searchHistoryList="searchHistoryList"></add>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import {
|
||||
defineComponent,
|
||||
ref,
|
||||
createVNode,
|
||||
computed,
|
||||
reactive,
|
||||
toRefs,
|
||||
onMounted,
|
||||
} from "vue";
|
||||
import { formatTime } from "@/tool/util";
|
||||
import { useStore } from "vuex";
|
||||
import { Https } from "@/tool/https";
|
||||
import {getCookie,clonAllCookie} from '@/tool/cookie'
|
||||
import add from './add.vue'
|
||||
export default defineComponent({
|
||||
components: {add},
|
||||
setup() {
|
||||
const store:any = useStore()
|
||||
let filter: any = reactive({
|
||||
dataList: [],
|
||||
tableLoading: false,
|
||||
countryList: computed(()=>{
|
||||
return store.state.adminPage.country
|
||||
}),
|
||||
add:null as any,
|
||||
status:'',
|
||||
});
|
||||
let filterData: any = reactive({
|
||||
currentPage: 1,
|
||||
pageSize: 10,
|
||||
total: 0,
|
||||
country: "",
|
||||
status: "",
|
||||
type: "",
|
||||
});
|
||||
let selectList=reactive({
|
||||
statusList:[
|
||||
{
|
||||
label: "all",
|
||||
value: "",
|
||||
import {
|
||||
defineComponent,
|
||||
ref,
|
||||
createVNode,
|
||||
computed,
|
||||
reactive,
|
||||
toRefs,
|
||||
onMounted,
|
||||
} from "vue";
|
||||
import { formatTime } from "@/tool/util";
|
||||
import { useStore } from "vuex";
|
||||
import { Https } from "@/tool/https";
|
||||
import { getCookie, clonAllCookie } from "@/tool/cookie";
|
||||
import add from "./add.vue";
|
||||
export default defineComponent({
|
||||
components: { add },
|
||||
setup() {
|
||||
const store: any = useStore();
|
||||
let filter: any = reactive({
|
||||
dataList: [],
|
||||
tableLoading: false,
|
||||
countryList: computed(() => {
|
||||
return store.state.adminPage.country;
|
||||
}),
|
||||
add: null as any,
|
||||
});
|
||||
let filterData: any = reactive({
|
||||
currentPage: 1,
|
||||
pageSize: 10,
|
||||
total: 0,
|
||||
country: "",
|
||||
status: "",
|
||||
school: "",
|
||||
rangePickerValue: [],
|
||||
});
|
||||
let selectList = reactive({
|
||||
statusList: [
|
||||
{
|
||||
label: "all",
|
||||
value: "",
|
||||
},
|
||||
{
|
||||
label: "Enterprise",
|
||||
value: "Enterprise",
|
||||
},
|
||||
{
|
||||
label: "Education",
|
||||
value: "Education",
|
||||
},
|
||||
],
|
||||
schoolList: [],
|
||||
});
|
||||
let renameData: any = ref({}); //修改名字选中的数据
|
||||
const columns: any = computed(() => {
|
||||
return [
|
||||
{
|
||||
title: "Id",
|
||||
align: "center",
|
||||
dataIndex: "id",
|
||||
key: "id",
|
||||
width: 150,
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
title: "Name",
|
||||
align: "center",
|
||||
dataIndex: "name",
|
||||
key: "name",
|
||||
width: 150,
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
title: "Create Time",
|
||||
align: "center",
|
||||
dataIndex: "createTime",
|
||||
key: "createTime",
|
||||
width: 150,
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
title: "Type",
|
||||
align: "center",
|
||||
dataIndex: "type",
|
||||
key: "type",
|
||||
width: 150,
|
||||
ellipsis: true,
|
||||
},
|
||||
];
|
||||
});
|
||||
//改变页码
|
||||
let changePage = (e: any, filters: any, sorter: any) => {
|
||||
filterData.currentPage = e.current;
|
||||
filterData.pageSize = e.pageSize;
|
||||
gettrialList();
|
||||
};
|
||||
const filterOption = (e: any) => {
|
||||
let type = filterData.status;
|
||||
if (type == "Education") type = "School";
|
||||
let params = {
|
||||
name: e,
|
||||
type,
|
||||
};
|
||||
Https.axiosPost(
|
||||
Https.httpUrls.organizationNameSearch,
|
||||
{},
|
||||
{ params: params }
|
||||
).then((rv: any) => {
|
||||
if (rv.length == 0) return (selectList.schoolList = []);
|
||||
selectList.schoolList = rv.map((item: any) => {
|
||||
return {
|
||||
label: item,
|
||||
value: item,
|
||||
};
|
||||
});
|
||||
});
|
||||
};
|
||||
//查询列表
|
||||
let searchHistoryList = () => {
|
||||
filterData.currentPage = 1;
|
||||
gettrialList();
|
||||
};
|
||||
//获取列表
|
||||
let gettrialList = () => {
|
||||
filter.tableLoading = true;
|
||||
const dateArr = filterData.rangePickerValue;
|
||||
const startDate = dateArr?.[0] ? dateArr[0] + " " + "00:00:00" : "";
|
||||
const endDate = dateArr?.[1] ? dateArr[1] + " " + "23:59:59" : "";
|
||||
const params = {
|
||||
startTime: startDate,
|
||||
endTime: endDate,
|
||||
id: "",
|
||||
name: filterData.school,
|
||||
type: filterData.status,
|
||||
size: filterData.pageSize,
|
||||
page: filterData.currentPage,
|
||||
}; //type: "Enterprise"
|
||||
Https.axiosPost(Https.httpUrls.queryOrganization, params).then(
|
||||
(rv: any) => {
|
||||
if (rv) {
|
||||
console.log(rv);
|
||||
// filter.dataList = rv;
|
||||
filter.dataList = rv.records;
|
||||
filterData.total = rv.total;
|
||||
filter.tableLoading = false;
|
||||
// this.workspaceItem.position = this.singleTypeList[0].label
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
let addhHistoryList = () => {
|
||||
filter.add.init("Add", "");
|
||||
};
|
||||
const handleFocus = () => {
|
||||
if (selectList.schoolList.length == 0) {
|
||||
filterOption("");
|
||||
}
|
||||
};
|
||||
const changeStatus = () => {
|
||||
filterData.school = "";
|
||||
selectList.schoolList = [];
|
||||
};
|
||||
onMounted(() => {
|
||||
gettrialList();
|
||||
});
|
||||
return {
|
||||
...toRefs(filter),
|
||||
...toRefs(filterData),
|
||||
...toRefs(selectList),
|
||||
columns,
|
||||
renameData,
|
||||
changePage,
|
||||
searchHistoryList,
|
||||
gettrialList,
|
||||
addhHistoryList,
|
||||
handleFocus,
|
||||
changeStatus,
|
||||
};
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
historyTableHeight: 0,
|
||||
handleResizeColumn: (w: any, col: any) => {
|
||||
col.width = w;
|
||||
},
|
||||
{
|
||||
label:'Enterprise',
|
||||
value:'Enterprise',
|
||||
},
|
||||
{
|
||||
label:'Education',
|
||||
value:'Education',
|
||||
},
|
||||
],
|
||||
})
|
||||
let renameData: any = ref({}); //修改名字选中的数据
|
||||
const columns: any = computed(() => {
|
||||
return [
|
||||
{
|
||||
title: "Id",
|
||||
align: "center",
|
||||
dataIndex: "id",
|
||||
key: "id",
|
||||
width:150,
|
||||
ellipsis:true
|
||||
},
|
||||
{
|
||||
title: "Name",
|
||||
align: "center",
|
||||
dataIndex: "name",
|
||||
key: "name",
|
||||
width:150,
|
||||
ellipsis:true
|
||||
},
|
||||
{
|
||||
title: "Create Time",
|
||||
align: "center",
|
||||
dataIndex: "createTime",
|
||||
key: "createTime",
|
||||
width:150,
|
||||
ellipsis:true
|
||||
},
|
||||
{
|
||||
title: "Type",
|
||||
align: "center",
|
||||
dataIndex: "type",
|
||||
key: "type",
|
||||
width:150,
|
||||
ellipsis:true,
|
||||
},
|
||||
];
|
||||
});
|
||||
//改变页码
|
||||
let changePage = (e: any, filters:any, sorter:any) => {
|
||||
filterData.currentPage = e.current;
|
||||
filterData.pageSize = e.pageSize;
|
||||
gettrialList();
|
||||
};
|
||||
|
||||
//查询列表
|
||||
let searchHistoryList = () => {
|
||||
filterData.currentPage = 1;
|
||||
gettrialList();
|
||||
};
|
||||
//获取列表
|
||||
let gettrialList = () => {
|
||||
filter.tableLoading = true;
|
||||
Https.axiosGet(Https.httpUrls.queryOrganization, {params:{type:'Enterprise'}}).then(
|
||||
(rv: any) => {
|
||||
if (rv) {
|
||||
console.log(rv)
|
||||
filter.dataList = rv
|
||||
// filter.dataList = rv.content;
|
||||
// filterData.total = rv.total;
|
||||
filter.tableLoading = false;
|
||||
|
||||
// this.workspaceItem.position = this.singleTypeList[0].label
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
let addhHistoryList = () => {
|
||||
filter.add.init('Add','')
|
||||
};
|
||||
onMounted(() => {
|
||||
gettrialList();
|
||||
});
|
||||
return {
|
||||
...toRefs(filter),
|
||||
...toRefs(filterData),
|
||||
...toRefs(selectList),
|
||||
columns,
|
||||
renameData,
|
||||
changePage,
|
||||
searchHistoryList,
|
||||
gettrialList,
|
||||
addhHistoryList,
|
||||
};
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
historyTableHeight: 0,
|
||||
handleResizeColumn: (w: any, col: any) => {
|
||||
col.width = w;
|
||||
},
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
let historyTable: any = this.$refs.historyTable;
|
||||
this.historyTableHeight = historyTable.clientHeight - 200;
|
||||
},
|
||||
methods: {},
|
||||
});
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
let historyTable: any = this.$refs.historyTable;
|
||||
this.historyTableHeight = historyTable.clientHeight - 200;
|
||||
},
|
||||
methods: {},
|
||||
});
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.admin_page .admin_table_search .admin_state {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
:deep(.operate_list){
|
||||
.fi{
|
||||
font-size: 2rem;
|
||||
margin-right: 1rem;
|
||||
.admin_page .admin_table_search .admin_state {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.success{
|
||||
.fi-ss-check-circle{
|
||||
color: #3ab45c;
|
||||
:deep(.operate_list) {
|
||||
.fi {
|
||||
font-size: 2rem;
|
||||
margin-right: 1rem;
|
||||
}
|
||||
.success {
|
||||
.fi-ss-check-circle {
|
||||
color: #3ab45c;
|
||||
}
|
||||
}
|
||||
.pending {
|
||||
.fi-ss-check-circle {
|
||||
color: #ffc628;
|
||||
}
|
||||
}
|
||||
.fail {
|
||||
.fi-ss-check-circle {
|
||||
color: #ff0000;
|
||||
}
|
||||
}
|
||||
}
|
||||
.pending{
|
||||
.fi-ss-check-circle{
|
||||
color: #ffc628;
|
||||
}
|
||||
}
|
||||
.fail{
|
||||
.fi-ss-check-circle{
|
||||
color: #ff0000;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -10,6 +10,8 @@ import { fabric } from "fabric-with-all";
|
||||
import { generateId } from "../utils/helper.js";
|
||||
import { ClearSelectionCommand } from "./LassoCutoutCommand.js";
|
||||
import { ClearSelectionContentCommand } from "./ClearSelectionContentCommand.js";
|
||||
import i18n from "@/lang/index.ts";
|
||||
const { t } = i18n.global;
|
||||
|
||||
/**
|
||||
* 剪切选区到新图层命令
|
||||
@@ -36,7 +38,7 @@ export class CutSelectionToNewLayerCommand extends CompositeCommand {
|
||||
this.baseResolutionScale = options.baseResolutionScale || 2; // 基础分辨率倍数
|
||||
|
||||
this.groupId = options.groupId || generateId("lasso-copy-group-");
|
||||
this.groupName = options.groupName || `选区组`;
|
||||
this.groupName = options.groupName || t(`Canvas.ConstituencyGroup`);
|
||||
this.groupLayer = null; // 新增:保存组图层的引用
|
||||
this.originalLayersLength = 0; // 新增:保存原始图层数量
|
||||
|
||||
@@ -179,7 +181,7 @@ export class CutSelectionToNewLayerCommand extends CompositeCommand {
|
||||
// 创建新的组图层
|
||||
this.groupLayer = createLayer({
|
||||
id: this.groupId,
|
||||
name: this.groupName || `选区组`,
|
||||
name: this.groupName || t(`Canvas.ConstituencyGroup`),
|
||||
type: LayerType.GROUP,
|
||||
visible: true,
|
||||
locked: false,
|
||||
|
||||
@@ -11,6 +11,10 @@ import {
|
||||
} from "./LayerCommands.js";
|
||||
import { fabric } from "fabric-with-all";
|
||||
import { generateId } from "../utils/helper.js";
|
||||
import i18n from "@/lang/index.ts";
|
||||
const { t } = i18n.global;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 套索抠图命令
|
||||
@@ -37,7 +41,7 @@ export class LassoCutoutCommand extends CompositeCommand {
|
||||
this.baseResolutionScale = options.baseResolutionScale || 2; // 基础分辨率倍数
|
||||
|
||||
this.groupId = options.groupId || generateId("lasso-group-");
|
||||
this.groupName = options.groupName || `选区组`;
|
||||
this.groupName = options.groupName || t(`Canvas.ConstituencyGroup`);
|
||||
|
||||
this.clippingMaskId = generateId("clipping-mask-");
|
||||
|
||||
@@ -238,7 +242,7 @@ export class LassoCutoutCommand extends CompositeCommand {
|
||||
// 创建新的组图层
|
||||
this.groupLayer = createLayer({
|
||||
id: this.groupId,
|
||||
name: this.groupName || `选区组`,
|
||||
name: this.groupName || t(`Canvas.ConstituencyGroup`),
|
||||
type: LayerType.GROUP,
|
||||
visible: true,
|
||||
locked: false,
|
||||
|
||||
@@ -13,6 +13,9 @@ import {
|
||||
import { fabric } from "fabric-with-all";
|
||||
import { generateId } from "../utils/helper.js";
|
||||
import { ToolCommand } from "./ToolCommands.js";
|
||||
import i18n from "@/lang/index.ts";
|
||||
const { t } = i18n.global;
|
||||
|
||||
|
||||
/**
|
||||
* 套索抠图命令
|
||||
@@ -39,7 +42,7 @@ export class LassoCutoutCommand extends CompositeCommand {
|
||||
this.baseResolutionScale = options.baseResolutionScale || 2; // 基础分辨率倍数
|
||||
|
||||
this.groupId = options.groupId || generateId("lasso-group-");
|
||||
this.groupName = options.groupName || `选区组`;
|
||||
this.groupName = options.groupName || t(`Canvas.ConstituencyGroup`);
|
||||
|
||||
this.clippingMaskId = generateId("clipping-mask-");
|
||||
|
||||
@@ -220,16 +223,26 @@ export class LassoCutoutCommand extends CompositeCommand {
|
||||
await clearSelectionCmd.execute();
|
||||
this.executedCommands.push(clearSelectionCmd);
|
||||
|
||||
const topLayerIndex = this.layerManager.layers.value.findIndex(
|
||||
(layer) => layer.id === this.originalLayer.id
|
||||
);
|
||||
const layers = this.layerManager.layers.value;
|
||||
var topLayerIndex = 0;
|
||||
layers.forEach((layer, index) => {
|
||||
if (layer.id === this.originalLayer.id) {
|
||||
topLayerIndex = index;
|
||||
}else if (layer.children.length > 0) {
|
||||
layer.children.forEach((childLayer) => {
|
||||
if (childLayer.id === this.originalLayer.id) {
|
||||
topLayerIndex = index;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// const selectLayer = this.layerManager.layers.value[topLayerIndex];
|
||||
|
||||
// 创建新的组图层
|
||||
this.groupLayer = createLayer({
|
||||
id: this.groupId,
|
||||
name: this.groupName || `选区组`,
|
||||
name: this.groupName || t(`Canvas.ConstituencyGroup`),
|
||||
type: LayerType.GROUP,
|
||||
visible: true,
|
||||
locked: false,
|
||||
@@ -244,7 +257,7 @@ export class LassoCutoutCommand extends CompositeCommand {
|
||||
// });
|
||||
|
||||
const selectLayer = createLayer({
|
||||
name: `选区空图层`,
|
||||
name: t(`Canvas.ConstituencyEmptyLayer`),
|
||||
type: LayerType.EMPTY,
|
||||
visible: true,
|
||||
locked: false,
|
||||
@@ -284,6 +297,7 @@ export class LassoCutoutCommand extends CompositeCommand {
|
||||
|
||||
this.groupLayer.children.push(selectLayer);
|
||||
// 插入新组图层
|
||||
console.log("新增套索添加index", topLayerIndex);
|
||||
this.layerManager.layers.value.splice(topLayerIndex, 0, this.groupLayer);
|
||||
|
||||
this.layerManager.activeLayerId.value = selectLayer.id; // 设置新组图层为活动图层
|
||||
|
||||
@@ -116,7 +116,7 @@ export class AddLayerCommand extends Command {
|
||||
parentLayer.children.splice(insertIndex, 0, newLayer);
|
||||
|
||||
console.log(
|
||||
`新图层已插入到子图层位置: ${insertIndex} (父图层: ${parentLayer.name})`
|
||||
`新图层已插入到子图层位置: ${insertIndex} (父图层: ${parentLayer.name})`
|
||||
);
|
||||
} else {
|
||||
// 当前激活图层是一级图层
|
||||
@@ -2569,7 +2569,6 @@ export class CreateImageLayerCommand extends Command {
|
||||
this.fabricImage = options.fabricImage;
|
||||
this.toolManager = options.toolManager;
|
||||
this.layerName = options.layerName || null;
|
||||
|
||||
this.imageId = generateId("image_");
|
||||
|
||||
// 存储执行过程中的结果
|
||||
@@ -2617,6 +2616,18 @@ export class CreateImageLayerCommand extends Command {
|
||||
this.commands.push(createLayerCmd);
|
||||
this.executedCommands.push(createLayerCmd);
|
||||
|
||||
// 新加功能-选区套索内添加图片自动居中
|
||||
const { parent } = findLayerRecursively(this.layerManager.layers.value, this.newLayerId);
|
||||
if(parent && parent.selectObject){
|
||||
let {top,left,width,height} = parent.selectObject;
|
||||
const ltop = top + height / 2;
|
||||
const lleft = left + width / 2;
|
||||
this.fabricImage.set({
|
||||
top: ltop,
|
||||
left: lleft,
|
||||
})
|
||||
}
|
||||
|
||||
// 2. 添加图片对象到图层命令
|
||||
const addObjectCmd = new AddObjectToLayerCommand({
|
||||
canvas: this.layerManager.canvas,
|
||||
@@ -4197,6 +4208,7 @@ export class RemoveChildLayerCommand extends Command {
|
||||
this.isActiveLayer = this.layerId === this.activeLayerId.value;
|
||||
|
||||
this.originalObjects = this.canvas.getObjects().filter((obj) => {
|
||||
obj.parentId = this.parentId;
|
||||
return obj.layerId === this.layerId;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { generateId, optimizeCanvasRendering } from "../utils/helper";
|
||||
import { createLayer, LayerType, OperationType } from "../utils/layerHelper";
|
||||
import { Command } from "./Command";
|
||||
import i18n from "@/lang/index.ts";
|
||||
const { t } = i18n.global;
|
||||
|
||||
/**
|
||||
* 文本内容命令
|
||||
@@ -329,7 +331,7 @@ export class CreateTextCommand extends Command {
|
||||
|
||||
// 默认文本属性
|
||||
this.defaultOptions = {
|
||||
text: "双击编辑文本",
|
||||
text: t('Canvas.DoubleClickText'),
|
||||
fontFamily: "Arial",
|
||||
fontSize: 24,
|
||||
fontWeight: "normal",
|
||||
|
||||
@@ -362,6 +362,11 @@ watch(
|
||||
setBrushSize(newSize);
|
||||
}
|
||||
);
|
||||
watch(()=>isVisible.value, (newVisible) => {
|
||||
if (newVisible) {
|
||||
setBrushSize(brushSize.value);
|
||||
}
|
||||
})
|
||||
|
||||
// 监听brushOpacity的变化,更新到BrushStore
|
||||
watch(
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
@click="setBrushTypeWithCommand(brush.id)"
|
||||
:class="['brush-type-item', { active: brushStore.state.type === brush.id }]"
|
||||
>
|
||||
<div class="brush-preview" :style="getBrushPreviewStyle(brush)"></div>
|
||||
<!-- <div class="brush-preview" :style="getBrushPreviewStyle(brush)"></div> -->
|
||||
<img class="brush-preview" :src="brush.imgUrl" :title="brush.name" alt="">
|
||||
<span class="brush-name">{{ brush.name }}</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -189,7 +190,7 @@
|
||||
</div>
|
||||
<div class="uploaded-textures-section">
|
||||
<div class="uploaded-textures-divider">
|
||||
<span>{{ $t("上传的纹理") }}</span>
|
||||
<span>{{ $t("Canvas.UploadedTexture") }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="texture-grid">
|
||||
@@ -200,7 +201,7 @@
|
||||
<div class="upload-icon">
|
||||
<span>+</span>
|
||||
</div>
|
||||
<span class="texture-label">{{ $t("上传纹理") }}</span>
|
||||
<span class="texture-label">{{ $t("Canvas.UploadTexture") }}</span>
|
||||
</div>
|
||||
<div
|
||||
v-for="textureId in brushStore.state.uploadedTextures"
|
||||
@@ -218,7 +219,7 @@
|
||||
<div
|
||||
class="texture-remove-btn"
|
||||
@click.stop="removeUploadedTexture(textureId)"
|
||||
:title="$t('删除纹理')"
|
||||
:title="$t('Canvas.DeleteTexture')"
|
||||
>
|
||||
<span>×</span>
|
||||
</div>
|
||||
@@ -534,6 +535,9 @@ import {
|
||||
TextureUploadCommand,
|
||||
} from "../commands/BrushCommands";
|
||||
import { debounce } from "lodash-es";
|
||||
import { useI18n } from "vue-i18n";
|
||||
const { t } = useI18n();
|
||||
|
||||
|
||||
// 从工具管理器获取可用笔刷类型
|
||||
const toolManager = inject("toolManager");
|
||||
@@ -872,7 +876,7 @@ function applyPresetWithCommand(presetIndex) {
|
||||
// 保存当前设置为预设
|
||||
function saveCurrentAsPreset() {
|
||||
// 简单实现,可以后续优化为弹窗输入名称
|
||||
const name = prompt("请输入预设名称:", `预设 ${BrushStore.state.presets.length + 1}`);
|
||||
const name = prompt(t('Canvas.presetNamePrompt'), `${t('Canvas.preset')} ${BrushStore.state.presets.length + 1}`);
|
||||
if (name) {
|
||||
const presetIndex = BrushStore.saveCurrentAsPreset(name);
|
||||
// 应用新创建的预设(可选)
|
||||
@@ -886,6 +890,7 @@ onMounted(() => {
|
||||
const availableBrushes = toolManager.brushManager
|
||||
.getBrushTypes()
|
||||
?.filter((brush) => brush.id !== "eraser");
|
||||
console.log(availableBrushes)
|
||||
BrushStore.setAvailableBrushes(availableBrushes);
|
||||
}
|
||||
});
|
||||
@@ -1178,6 +1183,8 @@ const brushStore = BrushStore;
|
||||
margin-bottom: 8px;
|
||||
border-radius: 4px;
|
||||
background-color: rgba(0, 0, 0, 0.02);
|
||||
object-fit: contain;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
/* 保持笔刷预览内容样式一致 */
|
||||
|
||||
@@ -136,7 +136,7 @@ function convertShortcuts(managerShortcuts) {
|
||||
action: actionDisplay,
|
||||
windows: shortcut.key.replace(/cmdOrCtrl\+/g, "Ctrl+"),
|
||||
mac: shortcut.key.replace(/cmdOrCtrl\+/g, "⌘+"),
|
||||
touch: shortcut.touch || "触控界面点击对应工具",
|
||||
touch: shortcut.touch || t('Canvas.touchTools'),
|
||||
displayKey: shortcut.displayKey,
|
||||
});
|
||||
}
|
||||
@@ -326,8 +326,8 @@ function getShortcutsByCategory(category) {
|
||||
<span v-else-if="platform.isIPad">iPad</span>
|
||||
<span v-else-if="platform.isIOS">iOS</span>
|
||||
<span v-else-if="platform.isAndroid">Android</span>
|
||||
<span v-else>其他</span>
|
||||
<span v-if="platform.isTouchDevice"> (触控设备)</span>
|
||||
<span v-else>{{ $t('Canvas.other') }}</span>
|
||||
<span v-if="platform.isTouchDevice"> ({{ $t('Canvas.touchDevice') }})</span>
|
||||
</div>
|
||||
|
||||
<div class="shortcuts-category">
|
||||
@@ -421,14 +421,14 @@ function getShortcutsByCategory(category) {
|
||||
</div> -->
|
||||
|
||||
<div class="touch-tips" v-if="platform.isTouchDevice">
|
||||
<h3>触控设备提示</h3>
|
||||
<h3>{{ $t('Canvas.touchDevicePrompts') }}</h3>
|
||||
<ul>
|
||||
<li>长按图层面板可访问更多选项</li>
|
||||
<li>双击元素可快速进入编辑模式</li>
|
||||
<li>双指拖动可平移画布</li>
|
||||
<li>双指捏合可缩放画布</li>
|
||||
<li>双指连按可显示元素变换控制点</li>
|
||||
<li>三指左右滑动可进行撤销/重做操作</li>
|
||||
<li>{{ $t('Canvas.touchDevicePrompts_1') }}</li>
|
||||
<li>{{ $t('Canvas.touchDevicePrompts_2') }}</li>
|
||||
<li>{{ $t('Canvas.touchDevicePrompts_3') }}</li>
|
||||
<li>{{ $t('Canvas.touchDevicePrompts_4') }}</li>
|
||||
<li>{{ $t('Canvas.touchDevicePrompts_5') }}</li>
|
||||
<li>{{ $t('Canvas.touchDevicePrompts_6') }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</Skeleton>
|
||||
|
||||
@@ -258,6 +258,23 @@ const setClosePanel = ()=>{
|
||||
closePanel.value = !closePanel.value
|
||||
}
|
||||
|
||||
// 工具管理器和画布管理器
|
||||
const toolManager = inject("toolManager");
|
||||
const canvasManager = inject("canvasManager");
|
||||
|
||||
watch(size, (newSize, oldSize) => {
|
||||
setBrushIndicatorSize(newSize)
|
||||
|
||||
})
|
||||
// 设置笔刷指示器大小
|
||||
function setBrushIndicatorSize(size) {
|
||||
// 如果工具管理器存在,立即应用此更改
|
||||
console.log(`=========== ${size}`,toolManager);
|
||||
if (toolManager) {
|
||||
toolManager.updateBrushIndicatorSize(size);
|
||||
}
|
||||
}
|
||||
|
||||
// 监听当前工具变化 - 参考 SelectionPanel 的实现方式
|
||||
watch(
|
||||
() => props.activeTool,
|
||||
@@ -269,10 +286,11 @@ watch(
|
||||
// 如果面板未显示且有合适的目标对象,则显示面板
|
||||
if (!visible.value) {
|
||||
visible.value = true;
|
||||
closePanel.value = true
|
||||
closePanel.value = true
|
||||
// 检查是否有可液化的对象
|
||||
checkAndShowPanel();
|
||||
}
|
||||
setBrushIndicatorSize(size.value)
|
||||
} else {
|
||||
visible.value = false; // 切换到其他工具时隐藏面板
|
||||
// 切换到其他工具,隐藏液化面板
|
||||
@@ -444,16 +462,16 @@ function showPanel(event) {
|
||||
if (detail.layerStatus && detail.layerStatus.message) {
|
||||
console.log("液化操作提示:", detail.layerStatus.message);
|
||||
Modal.error({
|
||||
title: "错误提示",
|
||||
title: t('Canvas.ErrorMessage'),
|
||||
content: detail.layerStatus.message,
|
||||
okText: "确定",
|
||||
okText: t('Canvas.confirm'),
|
||||
centered: true,
|
||||
});
|
||||
} else {
|
||||
Modal.error({
|
||||
title: "错误提示",
|
||||
content: "未选择有效图像或图层不适合液化操作",
|
||||
okText: "确定",
|
||||
title: t('Canvas.ErrorMessage'),
|
||||
content: t('Canvas.LiquidationError'),
|
||||
okText: t('Canvas.confirm'),
|
||||
centered: true,
|
||||
});
|
||||
console.log("未选择有效图像或图层不适合液化操作");
|
||||
@@ -1634,24 +1652,26 @@ function stopPressTimer() {
|
||||
color: #333;
|
||||
border: 1px solid rgba(0, 0, 0, 0.05);
|
||||
padding-bottom: 12px;
|
||||
&.active{
|
||||
transform: translateY(100%);
|
||||
> .btn{
|
||||
> i{
|
||||
transform: rotate(90deg);
|
||||
&.active{
|
||||
transform: translateY(100%);
|
||||
> .btn{
|
||||
> i{
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
> .btn{
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
|
||||
> i{
|
||||
font-size: 1.4rem;
|
||||
display: block;
|
||||
transform: rotate(270deg);
|
||||
}
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
> i{
|
||||
font-size: 1.4rem;
|
||||
transform: rotate(270deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -145,10 +145,10 @@
|
||||
</div>
|
||||
<div class="dialog-buttons">
|
||||
<button class="cancel-btn" @click="cancelFeather">
|
||||
{{ $t("取消") }}
|
||||
{{ $t("Canvas.close") }}
|
||||
</button>
|
||||
<button class="confirm-btn" @click="applyFeather">
|
||||
{{ $t("确认") }}
|
||||
{{ $t("Canvas.confirmEdit") }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -159,7 +159,7 @@
|
||||
<div v-if="showColorPicker" class="dialog-overlay">
|
||||
<div class="dialog-container">
|
||||
<div class="dialog-header">
|
||||
<h3>{{ $t("选择填充颜色") }}</h3>
|
||||
<h3>{{ $t("Canvas.SelectFillColor") }}</h3>
|
||||
<button class="close-dialog-btn" @click="cancelColorPicker">
|
||||
×
|
||||
</button>
|
||||
@@ -168,10 +168,10 @@
|
||||
<input type="color" v-model="fillColor" class="color-picker" />
|
||||
<div class="dialog-buttons">
|
||||
<button class="cancel-btn" @click="cancelColorPicker">
|
||||
{{ $t("取消") }}
|
||||
{{ $t("Canvas.close") }}
|
||||
</button>
|
||||
<button class="confirm-btn" @click="confirmColorPicker">
|
||||
{{ $t("确认") }}
|
||||
{{ $t("Canvas.confirmEdit") }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -16,8 +16,9 @@ const emit = defineEmits([
|
||||
"zoom-out",
|
||||
"toggle-red-green-mode",
|
||||
"undo-redo-status-changed",
|
||||
"trigger-library"
|
||||
]);
|
||||
const {t} = useI18n()
|
||||
const {t,locale} = useI18n()
|
||||
const props = defineProps({
|
||||
activeTool: String,
|
||||
minimapEnabled: {
|
||||
@@ -151,6 +152,13 @@ const normalToolsList = ref([
|
||||
icon: { name: "CUpload", size: "26" },
|
||||
class: "upload-btn",
|
||||
},
|
||||
{
|
||||
id: "library",
|
||||
title: t("LibraryPage.library"),
|
||||
action: triggerLibrary,
|
||||
icon: { name: "CLibrary", size: "26" },
|
||||
class: "library-btn",
|
||||
},
|
||||
{
|
||||
id: "addText",
|
||||
title: t("Canvas.AddText"),
|
||||
@@ -158,6 +166,17 @@ const normalToolsList = ref([
|
||||
icon: { name: "CFont", size: "20" },
|
||||
class: "text-btn",
|
||||
},
|
||||
{
|
||||
id: "help",
|
||||
title: t("Canvas.help"),
|
||||
action: () => openTutorial(),
|
||||
icon: { name: "CHelp", size: "30" },
|
||||
class: "text-btn",
|
||||
style: {
|
||||
'position': 'absolute',
|
||||
'bottom': '0',
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
// 红绿图模式工具列表
|
||||
@@ -228,10 +247,22 @@ function triggerImageUpload() {
|
||||
emit("trigger-image-upload");
|
||||
}
|
||||
|
||||
function triggerLibrary() {
|
||||
emit("trigger-library");
|
||||
}
|
||||
|
||||
function addText() {
|
||||
emit("add-text");
|
||||
}
|
||||
|
||||
function openTutorial() {
|
||||
if(locale.value == 'ENGLISH'){
|
||||
window.open('https://aida-user-manual.super.site/specific-scenarios/freely-sketching-in-canvas', '_blank');
|
||||
}else{
|
||||
window.open('https://aida-user-manual-chinese.super.site/%e4%bd%bf%e7%94%a8%e7%94%bb%e5%b8%83%e8%bf%9b%e8%a1%8c%e7%bc%96%e8%be%91 ', '_blank');
|
||||
}
|
||||
}
|
||||
|
||||
function undo() {
|
||||
if (!canUndo.value) return;
|
||||
undoFun();
|
||||
@@ -327,19 +358,25 @@ const handleToolClick = (tool) => {
|
||||
@change="fillColorChange"
|
||||
style="width: 0; height: 0; opacity: 0"
|
||||
/>
|
||||
<div class="tools-list">
|
||||
<slot name="customToolsTop" :tool-button-props="{ activeTool, canUndo, canRedo }" />
|
||||
|
||||
<ToolButton
|
||||
v-for="tool in toolsList"
|
||||
:key="tool.id"
|
||||
:tool="tool"
|
||||
:active-tool="activeTool"
|
||||
:can-undo="canUndo"
|
||||
:can-redo="canRedo"
|
||||
@click="handleToolClick"
|
||||
/>
|
||||
|
||||
<!-- 自定义工具栏按钮插槽 -->
|
||||
<slot name="customTools" :tool-button-props="{ activeTool, canUndo, canRedo }" />
|
||||
<ToolButton
|
||||
v-for="tool in toolsList"
|
||||
:key="tool.id"
|
||||
:tool="tool"
|
||||
:active-tool="activeTool"
|
||||
:can-undo="canUndo"
|
||||
:can-redo="canRedo"
|
||||
@click="handleToolClick"
|
||||
tip-body
|
||||
/>
|
||||
|
||||
<!-- 自定义工具栏按钮插槽 -->
|
||||
<slot name="customToolsBottom" :tool-button-props="{ activeTool, canUndo, canRedo }" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -347,15 +384,25 @@ const handleToolClick = (tool) => {
|
||||
.tools-sidebar {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1.0rem;
|
||||
padding: 1.5rem 1.0rem;
|
||||
border-right: .1rem solid #e0e0e0;
|
||||
background-color: #ffffff;
|
||||
user-select: none;
|
||||
min-width: 5.8rem;
|
||||
height: 100%;
|
||||
padding-top: .5rem;
|
||||
padding-bottom: 4rem;
|
||||
/* overflow-y: auto; */
|
||||
/* overflow-x: hidden; */
|
||||
}
|
||||
.tools-list{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.red-green-mode {
|
||||
background-color: #fff4f4;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,9 @@ import { RedGreenModeManager } from "./managers/RedGreenModeManager";
|
||||
import texturePresetManager from "./managers/brushes/TexturePresetManager";
|
||||
import { BrushStore } from "./store/BrushStore";
|
||||
import cuowuImg from '@/assets/images/homePage/cuowu.svg'
|
||||
import { Https } from "@/tool/https";
|
||||
import SelectImages from '@/component/common/SelectImages.vue'
|
||||
import { UrlToFile } from '@/tool/util'
|
||||
|
||||
|
||||
// import { MinimapManager } from "./managers/minimap/MinimapManager";
|
||||
@@ -52,6 +55,7 @@ const emit = defineEmits([
|
||||
"trigger-red-green-mouseup", // 红绿图模式鼠标抬起事件
|
||||
"changeCanvas", // 画布变更事件
|
||||
"canvasInit", // 画布初始化事件
|
||||
"trigger-library", // 触发打开Library选择图片事件
|
||||
]);
|
||||
|
||||
const props = defineProps({
|
||||
@@ -101,6 +105,14 @@ const props = defineProps({
|
||||
type: Boolean,
|
||||
default: false, // 是否显示固定图层
|
||||
},
|
||||
isGeneral: { // 从generalMiniCanvas来的
|
||||
type: Boolean,
|
||||
default:false
|
||||
},
|
||||
isEdit: { // 从design点击喜欢过的图片,再点击顶部的编辑图标
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
});
|
||||
|
||||
// 引用和状态
|
||||
@@ -569,7 +581,6 @@ function zoomOut() {
|
||||
x: canvasManager.canvas.width / 2,
|
||||
y: canvasManager.canvas.height / 2,
|
||||
};
|
||||
|
||||
canvasManager.animateZoom(centerPoint, newZoom);
|
||||
}
|
||||
|
||||
@@ -601,7 +612,7 @@ async function addLayer() {
|
||||
await layerManager.createLayer(t("Canvas.EmptyLayer"));
|
||||
}
|
||||
async function addTopLayer() {
|
||||
await layerManager.createLayer("空图层", LayerType.EMPTY, {
|
||||
await layerManager.createLayer(t("Canvas.EmptyLayer"), LayerType.EMPTY, {
|
||||
insertTop: true,
|
||||
});
|
||||
}
|
||||
@@ -667,12 +678,20 @@ function deleteFun(){
|
||||
|
||||
function removeLayer(layerId) {
|
||||
// Check if this is the last layer - prevent deletion
|
||||
if (layers.value.length <= 2) {
|
||||
console.warn(
|
||||
var isChild = false;
|
||||
var parentLength = 0;
|
||||
layers.value.forEach((layer) => {
|
||||
if(layer.children.some(v => v.id == layerId)){
|
||||
isChild = true;
|
||||
parentLength = layer.children.length;
|
||||
}
|
||||
})
|
||||
if(isChild && parentLength == 1 || layers.value.length <= 3){
|
||||
console.warn(
|
||||
"Cannot delete the last layer. At least one layer must remain."
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (canvasManager && canvasManager.canvas) {
|
||||
const layerToRemove = layers.value.find((l) => l.id === layerId);
|
||||
@@ -727,6 +746,21 @@ function handleImageUpload(event) {
|
||||
});
|
||||
}
|
||||
|
||||
const selectImages = ref(null);
|
||||
const handleImageSelect = (data) => {
|
||||
UrlToFile(data.url,data.name).then((file)=>{
|
||||
handleImageUpload({ target: { files: [file] } })
|
||||
})
|
||||
}
|
||||
function triggerLibrary() {
|
||||
// console.log('CanvasEditor', '打开收藏')
|
||||
if (props.isGeneral || props.isEdit) {
|
||||
selectImages.value.init()
|
||||
} else {
|
||||
emit("trigger-library");
|
||||
}
|
||||
}
|
||||
|
||||
function handleAddText() {
|
||||
if (toolManager && canvasManager && canvasManager.canvas) {
|
||||
// 在画布中央创建文本
|
||||
@@ -828,6 +862,7 @@ const changeCanvas = async (command) => {
|
||||
setTimeout(async ()=>{
|
||||
const imageData = await canvasManager.exportImage({
|
||||
restoreOpacityInRedGreen: true, // 恢复红绿图模式下的透明度
|
||||
isCropByBg:true,
|
||||
});
|
||||
emit("trigger-red-green-mouseup", imageData);
|
||||
},100)
|
||||
@@ -1066,10 +1101,14 @@ defineExpose({
|
||||
@zoom-in="zoomIn"
|
||||
@zoom-out="zoomOut"
|
||||
@undo-redo-status-changed="changeCanvas"
|
||||
@trigger-library="triggerLibrary"
|
||||
>
|
||||
<template #customToolsTop="{ toolTopProps }">
|
||||
<slot name="customToolsTop" :tool-button-props="toolTopProps" />
|
||||
</template>
|
||||
<!-- 扩展插槽 -->
|
||||
<template #customTools="{ toolButtonProps }">
|
||||
<slot name="customTools" :tool-button-props="toolButtonProps" />
|
||||
<template #customToolsBottom="{ toolButtonProps }">
|
||||
<slot name="customToolsBottom" :tool-button-props="toolButtonProps" />
|
||||
</template>
|
||||
</ToolsSidebar>
|
||||
</div>
|
||||
@@ -1184,6 +1223,14 @@ defineExpose({
|
||||
style="display: none"
|
||||
@change="handleImageUpload"
|
||||
/>
|
||||
<SelectImages
|
||||
ref="selectImages"
|
||||
full-data
|
||||
radio
|
||||
@select="handleImageSelect"
|
||||
:api="Https.httpUrls.queryLibraryPage"
|
||||
isLibrary
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { fabric } from "fabric-with-all";
|
||||
import { OperationType } from "../utils/layerHelper";
|
||||
|
||||
/**
|
||||
* 笔刷指示器
|
||||
@@ -104,9 +105,8 @@ export class BrushIndicator {
|
||||
this.canvas.freeDrawingBrush &&
|
||||
this.canvas.freeDrawingBrush.type === "eraser";
|
||||
|
||||
if (!isBrushMode && !isEraserMode) {
|
||||
return;
|
||||
}
|
||||
const isLiquifyMode = this.canvas.toolId === OperationType.LIQUIFY;// 检查是否在液化模式
|
||||
if ([isBrushMode, isEraserMode, isLiquifyMode].every(v => !v)) return;
|
||||
|
||||
let hasChanges = false;
|
||||
|
||||
@@ -391,6 +391,9 @@ export class BrushIndicator {
|
||||
this._mouseEnterHandler = (e) => {
|
||||
if (this._shouldShowIndicator()) {
|
||||
this.show(e.e);
|
||||
const currentVpt = this.canvas.viewportTransform;
|
||||
this.staticCanvas.setViewportTransform([...currentVpt]);
|
||||
this.staticCanvas.renderAll();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -471,9 +474,12 @@ export class BrushIndicator {
|
||||
* @returns {Boolean} 是否显示
|
||||
*/
|
||||
_shouldShowIndicator() {
|
||||
// 检查画布是否在绘图模式
|
||||
if (!this.canvas.isDrawingMode) return false;
|
||||
|
||||
const isDrawingMode = this.canvas.isDrawingMode;// 检查画布是否在绘图模式
|
||||
const isLiquifyMode = this.canvas.toolId === OperationType.LIQUIFY;// 检查是否在液化模式
|
||||
// console.log(`笔刷指示器\n绘图模式:${isDrawingMode}\n液化模式:${isLiquifyMode}`)
|
||||
// 检查画布是否在绘图模式OR液化模式
|
||||
if ([isDrawingMode, isLiquifyMode].every(v => !v)) return false;
|
||||
|
||||
// 检查是否有笔刷
|
||||
if (!this.canvas.freeDrawingBrush) return false;
|
||||
|
||||
|
||||
@@ -137,7 +137,9 @@ export class ExportManager {
|
||||
return await this._exportWithCanvasSize(
|
||||
objectsToExport,
|
||||
expPicType,
|
||||
restoreOpacityInRedGreen
|
||||
restoreOpacityInRedGreen,
|
||||
isCropByBg, // 是否使用背景大小裁剪
|
||||
isEnhanceImg, // 是否是增强图片
|
||||
);
|
||||
}
|
||||
|
||||
@@ -224,7 +226,7 @@ export class ExportManager {
|
||||
const objectsToExport = this._collectObjectsByLayerOrder(
|
||||
null, // 导出所有图层
|
||||
isContainBg,
|
||||
isContainFixed
|
||||
isContainFixed,
|
||||
);
|
||||
|
||||
if (objectsToExport.length === 0) {
|
||||
@@ -549,7 +551,7 @@ export class ExportManager {
|
||||
return await this._exportWithCanvasSize(
|
||||
objectsToExport,
|
||||
expPicType,
|
||||
restoreOpacityInRedGreen
|
||||
restoreOpacityInRedGreen,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -373,6 +373,8 @@ export class ToolManager {
|
||||
// 设置工具特定的状态
|
||||
const tool = this.tools[toolId];
|
||||
if (tool && typeof tool.setup === "function") {
|
||||
console.log(`画布切换工具:${tool.name}(${toolId})`)
|
||||
this.canvas.toolId = toolId;
|
||||
tool.setup();
|
||||
}
|
||||
|
||||
@@ -450,6 +452,7 @@ export class ToolManager {
|
||||
if (!this.canvas) return;
|
||||
this.canvas.isDrawingMode = false;
|
||||
this.canvas.selection = true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -750,6 +753,7 @@ export class ToolManager {
|
||||
detail: panelDetail,
|
||||
})
|
||||
);
|
||||
this._enableBrushIndicator();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -759,14 +763,14 @@ export class ToolManager {
|
||||
* @private
|
||||
*/
|
||||
_showRasterizeConfirmModal(isGroup, layerId) {
|
||||
const title = "栅格化图层";
|
||||
const content = "需要先栅格化才能进行液化操作,是否立即栅格化?";
|
||||
const title = this.t("Canvas.RasterizedLayer");
|
||||
const content = this.t("Canvas.rasterizeImmediately");
|
||||
|
||||
Modal.confirm({
|
||||
title,
|
||||
content,
|
||||
okText: "确定栅格化",
|
||||
cancelText: "取消",
|
||||
okText: this.t("Canvas.ConfirmRasterization"),
|
||||
cancelText: this.t("Canvas.close"),
|
||||
centered: true,
|
||||
icon: h("span", { style: "color: #faad14;" }, "⚠️"),
|
||||
onOk: () => {
|
||||
@@ -800,8 +804,8 @@ export class ToolManager {
|
||||
if (!this.commandManager || !this.layerManager) return;
|
||||
// 显示加载Modal
|
||||
const loadingModal = Modal.info({
|
||||
title: "正在栅格化",
|
||||
content: "正在栅格化图层,请稍候...",
|
||||
title: this.t('Canvas.beingRasterized'),
|
||||
content: this.t('Canvas.waitRasterizing'),
|
||||
okButtonProps: { style: { display: "none" } },
|
||||
centered: true,
|
||||
closable: false,
|
||||
@@ -823,16 +827,16 @@ export class ToolManager {
|
||||
|
||||
if (result) {
|
||||
// 栅格化成功,启动液化
|
||||
message.success("图层已成功栅格化,可以进行液化操作");
|
||||
message.success(this.t('Canvas.successRasterizing'));
|
||||
this._startLiquify(result);
|
||||
|
||||
this.setTool(OperationType.LIQUIFY); // 切换到液化工具
|
||||
} else {
|
||||
// 栅格化失败
|
||||
Modal.error({
|
||||
title: "栅格化失败",
|
||||
content: "栅格化失败,无法进行液化操作",
|
||||
okText: "确定",
|
||||
title: this.t('Canvas.gridingFailed'),
|
||||
content: this.t('Canvas.gridingFailedNoOperation'),
|
||||
okText: this.t('Canvas.ok'),
|
||||
centered: true,
|
||||
});
|
||||
}
|
||||
@@ -840,9 +844,9 @@ export class ToolManager {
|
||||
console.error("栅格化图层失败:", error);
|
||||
|
||||
Modal.error({
|
||||
title: "栅格化错误",
|
||||
content: `栅格化失败:${error.message}`,
|
||||
okText: "确定",
|
||||
title: this.t('Canvas.gridingError'),
|
||||
content: `${this.t('Canvas.gridingFailed')}:${error.message}`,
|
||||
okText: this.t('Canvas.ok'),
|
||||
centered: true,
|
||||
});
|
||||
} finally {
|
||||
@@ -866,9 +870,9 @@ export class ToolManager {
|
||||
);
|
||||
if (!layer) {
|
||||
Modal.error({
|
||||
title: "图层错误",
|
||||
content: "图层不存在",
|
||||
okText: "确定",
|
||||
title: this.t('Canvas.LayerError'),
|
||||
content: this.t('Canvas.LayerDoesNotExist'),
|
||||
okText: this.t('Canvas.ok'),
|
||||
centered: true,
|
||||
});
|
||||
return;
|
||||
@@ -880,9 +884,9 @@ export class ToolManager {
|
||||
// 背景图层使用 fabricObject (单数)
|
||||
if (!layer.fabricObject) {
|
||||
Modal.warning({
|
||||
title: "背景图层为空",
|
||||
content: "背景图层为空,无法进行液化操作",
|
||||
okText: "确定",
|
||||
title: this.t('Canvas.backgroundEmpty'),
|
||||
content: this.t('Canvas.backgroundEmptyNoLiquidation'),
|
||||
okText: this.t('Canvas.ok'),
|
||||
centered: true,
|
||||
});
|
||||
return;
|
||||
@@ -892,9 +896,9 @@ export class ToolManager {
|
||||
// 普通图层使用 fabricObjects (复数)
|
||||
if (!layer.fabricObjects || layer.fabricObjects.length === 0) {
|
||||
Modal.warning({
|
||||
title: "图层为空",
|
||||
content: "图层为空,无法进行液化操作",
|
||||
okText: "确定",
|
||||
title: this.t('Canvas.layerEmpty'),
|
||||
content: this.t('Canvas.layerEmptyNoLiquidation'),
|
||||
okText: this.t('Canvas.ok'),
|
||||
centered: true,
|
||||
});
|
||||
return;
|
||||
@@ -906,9 +910,9 @@ export class ToolManager {
|
||||
const liquifyManager = this.canvasManager?.liquifyManager;
|
||||
if (!liquifyManager) {
|
||||
Modal.error({
|
||||
title: "液化管理器错误",
|
||||
content: "液化管理器未初始化",
|
||||
okText: "确定",
|
||||
title: this.t('Canvas.liqueficationManagerError'),
|
||||
content: this.t('Canvas.liqueficationManagerErrorInitialized'),
|
||||
okText: this.t('Canvas.ok'),
|
||||
centered: true,
|
||||
});
|
||||
return;
|
||||
@@ -917,8 +921,8 @@ export class ToolManager {
|
||||
try {
|
||||
// 显示准备中的Modal
|
||||
const preparingModal = Modal.info({
|
||||
title: "准备液化环境",
|
||||
content: "正在准备液化环境,请稍候...",
|
||||
title: this.t('Canvas.liquefactionEnvironment'),
|
||||
content: this.t('Canvas.liquefactionEnvironmentLoading'),
|
||||
okButtonProps: { style: { display: "none" } },
|
||||
centered: true,
|
||||
closable: false,
|
||||
@@ -963,9 +967,9 @@ export class ToolManager {
|
||||
} catch (error) {
|
||||
console.error("启动液化工具失败:", error);
|
||||
Modal.error({
|
||||
title: "液化工具启动失败",
|
||||
content: `启动液化工具失败:${error.message}`,
|
||||
okText: "确定",
|
||||
title: this.t('Canvas.LiqueficationFailed'),
|
||||
content: `${this.t('Canvas.LiqueficationFailed')}:${error.message}`,
|
||||
okText: this.t('Canvas.ok'),
|
||||
centered: true,
|
||||
});
|
||||
}
|
||||
@@ -1041,7 +1045,7 @@ export class ToolManager {
|
||||
_createTextDirect(x, y, options = {}) {
|
||||
// 默认文本属性
|
||||
const defaultOptions = {
|
||||
text: "双击编辑文本",
|
||||
text: this.t('Canvas.DoubleClickText'),
|
||||
fontFamily: "Arial",
|
||||
fontSize: 24,
|
||||
fontWeight: "normal",
|
||||
@@ -1188,6 +1192,7 @@ export class ToolManager {
|
||||
if (this.brushIndicator) {
|
||||
this.brushIndicator.dispose();
|
||||
this.brushIndicator = null;
|
||||
console.log("笔刷指示器已清理");
|
||||
}
|
||||
|
||||
// 移除文本编辑相关事件监听器
|
||||
@@ -1381,6 +1386,7 @@ export class ToolManager {
|
||||
if (!this.brushIndicator) return;
|
||||
|
||||
this.brushIndicator.updateSize(size);
|
||||
console.log(`笔刷指示器大小已更新为: ${size}`);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1391,6 +1397,7 @@ export class ToolManager {
|
||||
if (!this.brushIndicator) return;
|
||||
|
||||
this.brushIndicator.updateColor(color);
|
||||
console.log(`笔刷指示器颜色已更新为: ${color}`);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1465,6 +1472,7 @@ export class ToolManager {
|
||||
OperationType.ERASER,
|
||||
OperationType.RED_BRUSH,
|
||||
OperationType.GREEN_BRUSH,
|
||||
OperationType.LIQUIFY,
|
||||
];
|
||||
|
||||
return brushTools.includes(currentTool);
|
||||
|
||||
@@ -173,7 +173,7 @@ export class AnimationManager {
|
||||
this._zoomAnimation = null;
|
||||
|
||||
// 确保最终状态准确
|
||||
this._applyZoom(point, targetZoom, true);
|
||||
// this._applyZoom(point, targetZoom, true);
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -65,6 +65,7 @@ export class BrushManager {
|
||||
description: "基础铅笔工具,适合精细线条绘制",
|
||||
t:this.t,
|
||||
category: this.t('Canvas.BasicBrushes'),
|
||||
imgUrl:'./image/brush/pencil.jpg',
|
||||
});
|
||||
|
||||
// 注册材质笔刷
|
||||
@@ -73,6 +74,7 @@ export class BrushManager {
|
||||
description: "使用纹理图片作为笔刷,支持缩放和透明度",
|
||||
t:this.t,
|
||||
category: this.t('Canvas.BasicBrushes'),
|
||||
imgUrl:'./image/brush/texture.jpg',
|
||||
});
|
||||
|
||||
// 注册集成的笔刷类型
|
||||
@@ -81,54 +83,63 @@ export class BrushManager {
|
||||
description: "使用纹理图片作为笔刷,支持缩放和透明度",
|
||||
t:this.t,
|
||||
category: this.t('Canvas.BasicBrushes'),
|
||||
imgUrl:'./image/brush/crayon.jpg',
|
||||
});
|
||||
brushRegistry.register("fur", FurBrush, {
|
||||
name: this.t("Canvas.Fur"),
|
||||
description: "使用纹理图片作为笔刷,支持缩放和透明度",
|
||||
t:this.t,
|
||||
category: this.t('Canvas.BasicBrushes'),
|
||||
imgUrl:'./image/brush/fur.jpg',
|
||||
});
|
||||
brushRegistry.register("ink", InkBrush, {
|
||||
name: this.t("Canvas.Ink"),
|
||||
description: "墨水笔刷,适合书写和绘图",
|
||||
t:this.t,
|
||||
category: this.t('Canvas.BasicBrushes'),
|
||||
imgUrl:'./image/brush/ink.jpg',
|
||||
});
|
||||
brushRegistry.register("", LongfurBrush, {
|
||||
name: this.t("Canvas.Longfur"),
|
||||
description: "长毛发笔刷,适合绘制动物毛皮、草或头发",
|
||||
t:this.t,
|
||||
category: this.t('Canvas.BasicBrushes'),
|
||||
imgUrl:'./image/brush/longFur.jpg',
|
||||
});
|
||||
brushRegistry.register("writing", WritingBrush, {
|
||||
name: this.t("Canvas.Writing"),
|
||||
description: "书法笔刷,模拟中国传统书法毛笔效果,具有笔锋和墨色变化",
|
||||
t:this.t,
|
||||
category: this.t('Canvas.BasicBrushes'),
|
||||
imgUrl:'./image/brush/writing.jpg',
|
||||
});
|
||||
brushRegistry.register("marker", MarkerBrush, {
|
||||
name: this.t("Canvas.Marker"),
|
||||
description: "马克笔笔刷,适合粗线条和填充",
|
||||
t:this.t,
|
||||
category: this.t('Canvas.BasicBrushes'),
|
||||
imgUrl:'./image/brush/marker.jpg',
|
||||
});
|
||||
brushRegistry.register("pen", CustomPenBrush, {
|
||||
name: this.t("Canvas.Pen"),
|
||||
description: "自定义钢笔笔刷,适合书写和绘图",
|
||||
t:this.t,
|
||||
category: this.t('Canvas.BasicBrushes'),
|
||||
imgUrl:'./image/brush/pen.jpg',
|
||||
});
|
||||
brushRegistry.register("ribbon", RibbonBrush, {
|
||||
name: this.t("Canvas.Ribbon"),
|
||||
description: "丝带笔刷,适合创建流动的丝带效果",
|
||||
t:this.t,
|
||||
category: this.t('Canvas.BasicBrushes'),
|
||||
imgUrl:'./image/brush/ribbon.jpg',
|
||||
});
|
||||
brushRegistry.register("shaded", ShadedBrush, {
|
||||
name: this.t("Canvas.Shaded"),
|
||||
description: "阴影笔刷,适合创建渐变和阴影效果",
|
||||
t:this.t,
|
||||
category: this.t('Canvas.BasicBrushes'),
|
||||
imgUrl:'./image/brush/shaded.jpg',
|
||||
});
|
||||
|
||||
brushRegistry.register("spray", SprayBrush, {
|
||||
@@ -136,6 +147,7 @@ export class BrushManager {
|
||||
description: "模拟喷枪效果,创建散点效果",
|
||||
t:this.t,
|
||||
category: this.t('Canvas.BasicBrushes'),
|
||||
imgUrl:'./image/brush/spray.jpg',
|
||||
});
|
||||
|
||||
// brushRegistry.register("sketchy", SketchyBrush);
|
||||
@@ -365,6 +377,7 @@ export class BrushManager {
|
||||
description: brushInfo.metadata.description || "",
|
||||
category: brushInfo.metadata.category || "默认",
|
||||
icon: brushInfo.metadata.icon || null,
|
||||
imgUrl: brushInfo.metadata.imgUrl || null,
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { BaseBrush } from "../BaseBrush";
|
||||
import { fabric } from "fabric-with-all";
|
||||
import texturePresetManager from "../TexturePresetManager";
|
||||
import i18n from "@/lang/index.ts";
|
||||
const {t} = i18n.global;
|
||||
|
||||
/**
|
||||
* 纹理笔刷
|
||||
@@ -468,12 +470,12 @@ export class TextureBrush extends BaseBrush {
|
||||
const textureProperties = [
|
||||
{
|
||||
id: "textureSelector",
|
||||
name: "材质选择",
|
||||
name: t('Canvas.TextureSelector'),
|
||||
type: "texture-grid",
|
||||
defaultValue: this.selectedTextureId,
|
||||
options: textureOptions,
|
||||
description: "选择要使用的纹理",
|
||||
category: "纹理设置",
|
||||
description: t('Canvas.selectTexture'),
|
||||
category: t('Canvas.TextureSettings'),
|
||||
order: 100,
|
||||
hidden: allTextures.length === 0,
|
||||
},
|
||||
|
||||
@@ -706,7 +706,8 @@ export class CanvasEventManager {
|
||||
if (e.target.id) {
|
||||
// 如果该元素是分组图层的一部分,也更新分组图层的缩略图
|
||||
if (e.target.parentId) {
|
||||
setTimeout(() => this.updateLayerThumbnail(e.target.parentId), 50);
|
||||
// setTimeout(() => this.updateLayerThumbnail(e.target.parentId), 50);
|
||||
this.thumbnailManager.generateLayerThumbnail(e.target.parentId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
import { LiquifyWebGLManager } from "./LiquifyWebGLManager";
|
||||
import { LiquifyCPUManager } from "./LiquifyCPUManager";
|
||||
import { findLayerRecursively, LayerType } from "../../utils/layerHelper";
|
||||
import i18n from "@/lang/index.ts";
|
||||
const {t} = i18n.global;
|
||||
|
||||
export class EnhancedLiquifyManager {
|
||||
/**
|
||||
@@ -20,13 +22,13 @@ export class EnhancedLiquifyManager {
|
||||
// 是否强制使用WebGL模式
|
||||
forceWebGL: options.forceWebGL || false,
|
||||
// 网格大小
|
||||
gridSize: options.gridSize || 15,
|
||||
gridSize: options.gridSize || 8,
|
||||
// 最大变形强度
|
||||
maxStrength: options.maxStrength || 100,
|
||||
maxStrength: options.maxStrength || 200,
|
||||
// 平滑迭代次数
|
||||
smoothingIterations: options.smoothingIterations || 2,
|
||||
smoothingIterations: options.smoothingIterations || 1,
|
||||
// 网格弹性因子
|
||||
relaxFactor: options.relaxFactor || 0.25,
|
||||
relaxFactor: options.relaxFactor || 0.05,
|
||||
// WebGL网格精度
|
||||
meshResolution: options.meshResolution || 64,
|
||||
};
|
||||
@@ -599,7 +601,7 @@ export class EnhancedLiquifyManager {
|
||||
if (objectsToCheck.length === 0) {
|
||||
return {
|
||||
valid: false,
|
||||
message: "图层为空,无法进行液化操作",
|
||||
message: t('Canvas.layerEmptyNoLiquidation'),
|
||||
needsRasterization: false,
|
||||
isImage: false,
|
||||
isEmpty: true,
|
||||
|
||||
@@ -31,10 +31,10 @@ export class LiquifyManager {
|
||||
// 创建增强版液化管理器实例
|
||||
this.enhancedManager = new EnhancedLiquifyManager({
|
||||
// 配置选项
|
||||
gridSize: options.gridSize || 15,
|
||||
maxStrength: options.maxStrength || 100,
|
||||
smoothingIterations: options.smoothingIterations || 2,
|
||||
relaxFactor: options.relaxFactor || 0.25,
|
||||
gridSize: options.gridSize || 8,
|
||||
maxStrength: options.maxStrength || 200,
|
||||
smoothingIterations: options.smoothingIterations || 1,
|
||||
relaxFactor: options.relaxFactor || 0.05,
|
||||
meshResolution: options.meshResolution || 64,
|
||||
// 根据环境选择合适的渲染模式
|
||||
forceCPU: true, // 默认不强制使用CPU
|
||||
|
||||
@@ -21,6 +21,10 @@ const props = defineProps({
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
tipBody: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(["click"]);
|
||||
@@ -47,10 +51,45 @@ const handleClick = () => {
|
||||
if (isDisabled.value) return;
|
||||
emit("click", props.tool);
|
||||
};
|
||||
|
||||
const tipId = "tooltip-" + Math.random().toString(36).substring(2);
|
||||
const el = ref(null);
|
||||
// 鼠标移入获取位置信息
|
||||
const handleMouseEnter = (e) => {
|
||||
const tooltip = el.value;
|
||||
const rect = tooltip.getBoundingClientRect();
|
||||
const left = rect.left + rect.width;
|
||||
const top = rect.top + rect.height / 2;
|
||||
const tip = document.getElementById(tipId);
|
||||
tip.style.position = 'fixed';
|
||||
tip.style.left = `${left}px`;
|
||||
tip.style.top = `${top}px`;
|
||||
tip.style.display = 'block';
|
||||
}
|
||||
// 鼠标移出隐藏提示
|
||||
const handleMouseLeave = () => {
|
||||
const tip = document.getElementById(tipId);
|
||||
tip.style.display = 'none';
|
||||
}
|
||||
onMounted(() => {
|
||||
if(props.tipBody){
|
||||
el.value.addEventListener('mouseenter', handleMouseEnter);
|
||||
el.value.addEventListener('mouseleave', handleMouseLeave);
|
||||
}
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
if(props.tipBody && el.value){
|
||||
el.value.removeEventListener('mouseenter', handleMouseEnter);
|
||||
el.value.removeEventListener('mouseleave', handleMouseLeave);
|
||||
}
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
ref="el"
|
||||
:class="[
|
||||
'tool-btn',
|
||||
tool.class,
|
||||
@@ -63,7 +102,10 @@ const handleClick = () => {
|
||||
@click="handleClick"
|
||||
>
|
||||
<SvgIcon :name="tool.icon.name" :size="tool.icon.size"></SvgIcon>
|
||||
<div class="tool-tooltip">{{ t(tool.title) }}</div>
|
||||
<teleport to="body" v-if="tipBody">
|
||||
<div class="tool-tooltip" :id="tipId">{{ t(tool.title) }}</div>
|
||||
</teleport>
|
||||
<div class="tool-tooltip" v-else>{{ t(tool.title) }}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -82,6 +124,7 @@ const handleClick = () => {
|
||||
font-size: 1.6rem;
|
||||
color: #333;
|
||||
transition: all 0.2s ease;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.tool-btn:hover {
|
||||
@@ -115,7 +158,7 @@ const handleClick = () => {
|
||||
margin-left: .8rem;
|
||||
white-space: nowrap;
|
||||
font-size: 1.2rem;
|
||||
z-index: 10;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
.tool-tooltip:before {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<div
|
||||
class="image-list-trigger"
|
||||
@click="showPanel = true"
|
||||
:title="$t('打开图片库')"
|
||||
:title="$t('Canvas.photoGallery')"
|
||||
>
|
||||
<SvgIcon name="CImageList" :size="20" />
|
||||
</div>
|
||||
@@ -56,6 +56,14 @@
|
||||
<span class="image-name">{{ item.name || "未命名" }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="image-select" v-show="selectList.includes(item.url)">
|
||||
<i class="fi fi-sr-check-circle"></i>
|
||||
</div> -->
|
||||
<img
|
||||
src="@/assets/images/icon/selected.png"
|
||||
class="image-select"
|
||||
v-show="selectList.includes(item.url)"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -70,6 +78,7 @@
|
||||
<div class="image-count">
|
||||
{{ $t("Canvas.general") }} {{ filteredImages.length }} {{ $t("Canvas.PicturesInTotal") }}
|
||||
</div>
|
||||
<div class="image-submit gallery_btn" @click="confirm">{{ $t("Canvas.confirm") }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -103,6 +112,7 @@ const emits = defineEmits(["select"]);
|
||||
// 响应式数据
|
||||
const showPanel = ref(false);
|
||||
const selectedCategory = ref(t("Canvas.all"));
|
||||
const selectList = ref([])
|
||||
|
||||
// 计算属性:获取所有分类
|
||||
const categories = computed(() => {
|
||||
@@ -152,8 +162,12 @@ const filteredImages = computed(() => {
|
||||
|
||||
// 处理图片点击
|
||||
const handleImageClick = (item) => {
|
||||
emits("select", item);
|
||||
showPanel.value = false;
|
||||
// 已选中,取消选中
|
||||
if(selectList.value.includes(item.url)){
|
||||
selectList.value = selectList.value.filter(url => url !== item.url)
|
||||
}else{
|
||||
selectList.value.push(item.url)
|
||||
}
|
||||
};
|
||||
|
||||
// 处理图片加载错误
|
||||
@@ -162,6 +176,13 @@ const handleImageError = (event) => {
|
||||
"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAwIiBoZWlnaHQ9IjIwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSIjZjVmNWY1Ii8+PHRleHQgeD0iNTAlIiB5PSI1MCUiIGZvbnQtZmFtaWx5PSJBcmlhbCwgc2Fucy1zZXJpZiIgZm9udC1zaXplPSIxNCIgZmlsbD0iIzk5OSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZHk9Ii4zZW0iPuWbvueJh+WKoOi9veWksei0pe+8jOivt+ajgOafpeWbvueJh+i3r+W+hDwvdGV4dD48L3N2Zz4=";
|
||||
event.target.alt = "图片加载失败";
|
||||
};
|
||||
|
||||
//提交选中的T图片
|
||||
const confirm = ()=>{
|
||||
emits("select", selectList.value);
|
||||
selectList.value = []
|
||||
showPanel.value = false;
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
@@ -368,10 +389,11 @@ const handleImageError = (event) => {
|
||||
.image-item {
|
||||
cursor: pointer;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
// overflow: hidden;
|
||||
transition: all 0.2s ease;
|
||||
background-color: #fff;
|
||||
border: 1px solid rgba(0, 0, 0, 0.05);
|
||||
position: relative;
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-4px);
|
||||
@@ -414,6 +436,17 @@ const handleImageError = (event) => {
|
||||
transition: opacity 0.2s ease;
|
||||
}
|
||||
|
||||
.image-select{
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
z-index: 2;
|
||||
transform: translate(50%,50%);
|
||||
i{
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.image-name {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
@@ -455,6 +488,10 @@ const handleImageError = (event) => {
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
> .image-submit{
|
||||
font-size: 1.2rem;
|
||||
line-height: 4rem;
|
||||
}
|
||||
}
|
||||
|
||||
.image-count {
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
:enabledRedGreenMode="true"
|
||||
:clothingImageUrl="imageUrls.baseImage"
|
||||
:redGreenImageUrl="imageUrls.maskImage"
|
||||
@trigger-red-green-mouseup="frontBackChange"
|
||||
:clothingImageOpts="{ imageMode: 'contains' }"
|
||||
/>
|
||||
</div>
|
||||
@@ -51,6 +52,9 @@ const loadJSON = () => {
|
||||
const changeFixedImage = () => {
|
||||
canvasEditor.value.changeFixedImage(changeImageUrl);
|
||||
};
|
||||
const frontBackChange = (value) =>{
|
||||
console.log(value)
|
||||
}
|
||||
|
||||
// 组件挂载时绑定键盘事件
|
||||
onMounted(() => {});
|
||||
|
||||
@@ -52,6 +52,7 @@ const imageData = [
|
||||
|
||||
const handleImageSelect = (selectedImage) => {
|
||||
console.log("选中的图片:", selectedImage);
|
||||
console.log(selectedImage)
|
||||
// selectedImage 包含:url, name, categoryName, categoryType, originalItem
|
||||
};
|
||||
|
||||
@@ -176,6 +177,10 @@ const canvasInit = () => {
|
||||
// });
|
||||
};
|
||||
|
||||
const frontBackChange =(value)=>{
|
||||
console.log(value)
|
||||
}
|
||||
|
||||
const isShowLeft = ref(true);
|
||||
</script>
|
||||
|
||||
@@ -195,6 +200,7 @@ const isShowLeft = ref(true);
|
||||
<RedGreenModeExample
|
||||
v-if="currentView === 'redGreenExample'"
|
||||
key="redGreenExample"
|
||||
@trigger-red-green-mouseup="frontBackChange"
|
||||
>
|
||||
</RedGreenModeExample>
|
||||
|
||||
@@ -218,7 +224,7 @@ const isShowLeft = ref(true);
|
||||
</template>
|
||||
|
||||
<!-- 使用插槽添加自定义工具栏按钮 -->
|
||||
<template #customTools="{ toolButtonProps }">
|
||||
<template #customToolsBottom="{ toolButtonProps }">
|
||||
<!-- 分隔线 -->
|
||||
<div class="tool-separator"></div>
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
:key="positionKey"
|
||||
@canvasReload="canvasReload"
|
||||
@detailEdit="detailEdit"
|
||||
@addSketch="()=>isEditPattern.value=false"
|
||||
@addSketch="()=>isEditPattern.value = ''"
|
||||
@revocation="revocation"
|
||||
@oppositeRevocation="oppositeRevocation"
|
||||
@modelOnLoad="modelOnLoad"
|
||||
@@ -69,7 +69,7 @@
|
||||
<div v-show="isEditPattern.value" style="margin-left: 2rem;" class="gallery_btn" @click="previwe">{{$t('DesignPrintOperation.Preview')}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item detailRight">
|
||||
<div class="item detailRight" :class="{canvas:isEditPattern.value}">
|
||||
<div class="submit">
|
||||
</div>
|
||||
<div class="contentRight" v-if="currentDetailType && !isEditPattern.value">
|
||||
@@ -88,7 +88,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="contentRight" v-if="selectDetail && selectDetail.id && currentDetailType && isEditPattern.value">
|
||||
<canvasBox ref="canvasBox" :key="canvasKey"></canvasBox>
|
||||
<canvasBox ref="canvasBox" :key="canvasKey || isEditPattern.value" :isEditPattern="isEditPattern.value"></canvasBox>
|
||||
</div>
|
||||
<!-- 画布 -->
|
||||
<!-- <div class="content" v-else-if="selectDetail && selectDetail.id">
|
||||
@@ -145,7 +145,7 @@ export default defineComponent({
|
||||
oppositeRevocationShow:-1,
|
||||
revocationShow:-1,
|
||||
isEditPattern:{
|
||||
value:false,
|
||||
value:'' as any,
|
||||
},// 是否编辑图案
|
||||
canvasKey:0,
|
||||
singleOveral:{
|
||||
@@ -158,6 +158,7 @@ export default defineComponent({
|
||||
isUndividedLayerWithSinglePrint:false,
|
||||
})
|
||||
|
||||
|
||||
provide('getCanvasIfEdit',detailData.getCanvasIfEdit)
|
||||
provide('singleOveral',detailData.singleOveral)
|
||||
provide('isEditPattern',detailData.isEditPattern)
|
||||
@@ -375,7 +376,7 @@ export default defineComponent({
|
||||
designSingleItemDTOList:clothes,
|
||||
isPreview:true,
|
||||
// ifSubmit:designItemDetail.isPreview,
|
||||
gender:workspace?.sex == 'Male'?1:0,
|
||||
gender:workspace?.sex,
|
||||
sketchString:'',
|
||||
modelId:(detailData.currentDetailType == 'models' && detailData.designDetail.newModel)?detailData.designDetail.newModel.id:detailData.designDetail.oldModel?detailData.designDetail.oldModel.id:'',
|
||||
modelType:(detailData.currentDetailType == 'models' && detailData.designDetail.newModel)?detailData.designDetail.newModel.type:detailData.designDetail.oldModel?detailData.designDetail.oldModel.type:'',
|
||||
@@ -451,11 +452,18 @@ export default defineComponent({
|
||||
})
|
||||
}
|
||||
const detailEdit = async (str:any)=>{
|
||||
if(str == 'edit'){
|
||||
if(detailData.isEditPattern.value){
|
||||
if(str){
|
||||
if(detailData.isEditPattern.value && detailData.isEditPattern.value == str){
|
||||
await detailDom.canvasBox.saveCanvas()
|
||||
detailData.isEditPattern.value = ''
|
||||
}else{
|
||||
if(detailData.isEditPattern.value){
|
||||
detailDom.canvasBox.editFront(str)
|
||||
}
|
||||
detailData.isEditPattern.value = str
|
||||
}
|
||||
detailData.isEditPattern.value = !detailData.isEditPattern.value
|
||||
}else{
|
||||
detailData.isEditPattern.value = ''
|
||||
}
|
||||
}
|
||||
const canvasReload = async ()=>{
|
||||
@@ -543,7 +551,7 @@ export default defineComponent({
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
:deep(.detailText){
|
||||
font-size: 1.8rem;
|
||||
font-size: 1.6rem;
|
||||
font-weight: 600;
|
||||
|
||||
}
|
||||
@@ -559,6 +567,7 @@ export default defineComponent({
|
||||
:deep(>div){
|
||||
> .ant-modal-root{
|
||||
> .ant-modal-centered{
|
||||
overflow: hidden;
|
||||
> .fullScreen{
|
||||
> .ant-modal-content{
|
||||
box-shadow: none;
|
||||
@@ -587,19 +596,28 @@ export default defineComponent({
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
&.detailLeft{
|
||||
width: 34rem;
|
||||
width: 30rem;
|
||||
// width: 34rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
overflow: hidden;
|
||||
}
|
||||
&.isEditPattern{width: 0px;}
|
||||
&.model{
|
||||
width: 50rem;
|
||||
margin: 0 10rem;
|
||||
flex: 1;
|
||||
// width: 45rem;
|
||||
// width: 50rem;
|
||||
margin: 0 8rem;
|
||||
// margin: 0 10rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
&.detailRight{
|
||||
flex: 1;
|
||||
width: 30%;
|
||||
&.canvas{
|
||||
width: 60%;
|
||||
}
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
// padding-bottom: calc(6rem + 1rem);
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
<editCanvas v-if="canvasLoad" :config="canvasConfig"
|
||||
@canvasInit="canvasInit"
|
||||
@changeCanvas="changeCanvas"
|
||||
is-edit
|
||||
:clothingImageUrl="selectDetail?.undividedLayerWithSinglePrint || selectDetail.undividedLayer || selectDetail.path"
|
||||
showFixedLayer
|
||||
:canvasJSON="canvasJSON"
|
||||
@@ -16,13 +17,6 @@
|
||||
imageMode:'contains',
|
||||
}"
|
||||
ref="editCanvas">
|
||||
<template #customTools="{ toolButtonProps }">
|
||||
<!-- 也可以直接使用普通的按钮 -->
|
||||
<div class="custom-tool-btn" :class="{active:currentView === 'redGreenExample'}" @click="editFront('redGreenExample')">
|
||||
<i class="fi fi-sr-layers"></i>
|
||||
<div class="tool-tooltip">Edit the front and back sections</div>
|
||||
</div>
|
||||
</template>
|
||||
</editCanvas>
|
||||
<!-- <canvasContent ref="canvasContent"></canvasContent> -->
|
||||
</div>
|
||||
@@ -34,20 +28,16 @@
|
||||
ref="editFrontBack">
|
||||
</editFrontBack> -->
|
||||
<editCanvas v-if="canvasLoad" :config="canvasConfig"
|
||||
@canvasInit="canvasInit"
|
||||
:enabledRedGreenMode="true"
|
||||
:clothingImageUrl="selectDetail.path"
|
||||
:redGreenImageUrl="frontBack.front[imgDomIndex].maskUrl"
|
||||
@trigger-red-green-mouseup="frontBackChange"
|
||||
is-edit
|
||||
:clothing-image-opts="{
|
||||
imageMode:'contains',
|
||||
}"
|
||||
ref="editCanvasBackFront">
|
||||
<template #customTools="{ toolButtonProps }">
|
||||
<div class="custom-tool-btn" :class="{active:currentView === 'redGreenExample'}" @click="editFront('canvasEditor')">
|
||||
<i class="fi fi-sr-layers"></i>
|
||||
<div class="tool-tooltip">Edit the front and back sections</div>
|
||||
</div>
|
||||
</template>
|
||||
</editCanvas>
|
||||
</div>
|
||||
</div>
|
||||
@@ -79,6 +69,10 @@ export default defineComponent({
|
||||
editCanvas
|
||||
},
|
||||
props:{
|
||||
isEditPattern:{
|
||||
type:String,
|
||||
default:''
|
||||
}
|
||||
},
|
||||
setup(props,{emit}) {
|
||||
const store = useStore();
|
||||
@@ -106,7 +100,7 @@ export default defineComponent({
|
||||
canvasLoad:false,
|
||||
canvasConfig:{
|
||||
} as any,
|
||||
currentView:'',
|
||||
currentView:props.isEditPattern,
|
||||
getCanvasIfEdit:inject('getCanvasIfEdit')as any,
|
||||
canvasInstance:null as any,
|
||||
canvasJSON:'',
|
||||
@@ -117,6 +111,7 @@ export default defineComponent({
|
||||
},{immediate: true})
|
||||
provide('isShowMark',detailData.isShowMark)
|
||||
provide('canvasType',detailData.canvasType)
|
||||
|
||||
const editFront = (str:any)=>{//编辑前后片
|
||||
|
||||
let canvasJSON = '' as any
|
||||
@@ -184,12 +179,55 @@ export default defineComponent({
|
||||
img.src = url
|
||||
})
|
||||
}
|
||||
|
||||
const resizeImageWithNativeCanvas = async (image1Url, imageBUrl)=>{
|
||||
try {
|
||||
// 加载第一张图片获取尺寸
|
||||
const img1 = await loadImage(image1Url);
|
||||
const targetWidth = img1.naturalWidth;
|
||||
const targetHeight = img1.naturalHeight;
|
||||
|
||||
// 加载第二张图片
|
||||
const imgB = await loadImage(imageBUrl);
|
||||
|
||||
// 创建canvas元素
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = targetWidth;
|
||||
canvas.height = targetHeight;
|
||||
const ctx = canvas.getContext('2d');
|
||||
|
||||
// 绘制调整尺寸后的图片
|
||||
ctx.drawImage(imgB, 0, 0, targetWidth, targetHeight);
|
||||
|
||||
// 导出base64
|
||||
const base64 = canvas.toDataURL('image/png', 1);
|
||||
|
||||
return base64;
|
||||
} catch (error) {
|
||||
console.error('处理图片时出错:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// 图片加载辅助函数
|
||||
const loadImage = (url)=>{
|
||||
return new Promise((resolve, reject) => {
|
||||
const img = new Image();
|
||||
img.crossOrigin = 'anonymous';
|
||||
img.onload = () => resolve(img);
|
||||
img.onerror = reject;
|
||||
img.src = url;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
const frontBackChange = (value:any)=>{
|
||||
let full = detailData.frontBack.front[detailData.imgDomIndex]?.undividedLayerWithSinglePrint || detailData.frontBack.front[detailData.imgDomIndex].undividedLayer || detailData.selectDetail.path
|
||||
let size = {
|
||||
...detailData.canvasConfig,
|
||||
}
|
||||
segmentImage(value,full,size).then((rv)=>{
|
||||
|
||||
segmentImage(value,full,size).then(async (rv)=>{
|
||||
let front = detailData.frontBack.front[detailData.imgDomIndex]
|
||||
let back = detailData.frontBack.back[detailData.imgDomIndex]
|
||||
if(!front?.oldImageUrl)front.oldImageUrl = front.imageUrl
|
||||
@@ -198,14 +236,14 @@ export default defineComponent({
|
||||
if(!front?.oldMaskUrl)store.commit('DesignDetail/updataDetailItem',{maskUrl:front.oldMaskUrl})
|
||||
|
||||
front.imageUrl = rv.targetFrontUrl
|
||||
front.maskUrl = value
|
||||
let base64 = await resizeImageWithNativeCanvas(front.oldMaskUrl,value)
|
||||
front.maskUrl = base64
|
||||
back.imageUrl = rv.targetBackUrl
|
||||
store.commit('DesignDetail/updataDetailItem',{maskUrl:value})
|
||||
})
|
||||
|
||||
}
|
||||
const canvasInit = (value:any)=>{
|
||||
// detailDom.editCanvas.addImageToLayer(detailData.selectDetail.undividedLayer,{layerId:value.layers.value[0].id,imageMode:'contains',undoable:false})
|
||||
detailData.canvasInstance = value
|
||||
detailData.getCanvasIfEdit.fun = getCanvasLength
|
||||
detailData.isShowMark = false
|
||||
@@ -254,9 +292,11 @@ export default defineComponent({
|
||||
saveCanvas('auto')
|
||||
},3000)
|
||||
}
|
||||
|
||||
onBeforeUnmount(()=>{
|
||||
let front = detailData.frontBack.front[detailData.imgDomIndex]
|
||||
let back = detailData.frontBack.back[detailData.imgDomIndex]
|
||||
|
||||
if(front?.oldImageUrl)front.imageUrl = front.oldImageUrl
|
||||
if(front?.oldMaskUrl)front.maskUrl = front.oldMaskUrl
|
||||
if(back?.oldImageUrl)back.imageUrl = back.oldImageUrl
|
||||
@@ -269,9 +309,7 @@ export default defineComponent({
|
||||
})
|
||||
onMounted(()=>{
|
||||
nextTick(async ()=>{
|
||||
detailData.currentView = 'canvasEditor'
|
||||
setTimeout(()=>{
|
||||
})
|
||||
// detailData.currentView = 'canvasEditor'
|
||||
if(detailData.selectDetail.canvasId){
|
||||
detailData.isShowMark = true
|
||||
await new Promise((resolve, reject) => {
|
||||
|
||||
@@ -16,8 +16,16 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="detailText">{{$t('DesignPrintOperation.Colorfromimage')}}</div>
|
||||
<div class="uploadImage">
|
||||
<upload @selectUplpadColor="selectUplpadColor"></upload>
|
||||
<div class="uploadImage flex flex-align-center flex-justify-center">
|
||||
<div class="upload-container" :class="{'hide': !showLibrary}">
|
||||
<upload ref="uploadRef" @selectUplpadColor="selectUplpadColor" @selectFile="showLibrary = false" @deleteColor="showLibrary = true"></upload>
|
||||
<div class="upload-text" v-show="showLibrary"> {{ $t('LibraryPage.Upload') }} </div>
|
||||
</div>
|
||||
<div class="upload-container " v-show="showLibrary">
|
||||
<!-- <i class="fi fi-rr-followcollection"></i> -->
|
||||
<SvgIcon name="CLibrary" class="svg-btn" size="20" @click="handleOpenLibrary" />
|
||||
<div class="upload-text"> {{ $t('LibraryPage.library') }} </div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="detailText">{{$t('DesignPrintOperation.ColorCode')}}</div>
|
||||
<div class="colorCode">
|
||||
@@ -30,7 +38,14 @@
|
||||
<!-- <div class="getTcxColorBtn" @click="getTcxColor">{{$t('DesignPrintOperation.ExtractColor')}}</div> -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<SelectImages
|
||||
ref="selectImages"
|
||||
@select="handleImageSelect"
|
||||
radio
|
||||
full-data
|
||||
:api="Https.httpUrls.queryLibraryPage"
|
||||
isLibrary
|
||||
/>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent,computed,ref,watch,nextTick,toRefs, reactive, onMounted} from 'vue'
|
||||
@@ -39,14 +54,16 @@ import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
|
||||
import { useStore } from "vuex";
|
||||
import { Https } from "@/tool/https";
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { rgbaToHex,rgbToHsv } from "@/tool/util"
|
||||
import { rgbaToHex,rgbToHsv,UrlToFile } from "@/tool/util"
|
||||
import { message,Upload} from 'ant-design-vue';
|
||||
import SelectImages from '@/component/common/SelectImages.vue'
|
||||
|
||||
|
||||
import upload from './upload.vue'
|
||||
import pallet from './pallet.vue'
|
||||
export default defineComponent({
|
||||
components:{
|
||||
upload,pallet
|
||||
upload,pallet,SelectImages
|
||||
},
|
||||
setup(props,{emit}) {
|
||||
const store = useStore();
|
||||
@@ -243,6 +260,30 @@ export default defineComponent({
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
const uploadRef = ref<any>(null)
|
||||
const selectImages = ref<any>(null)
|
||||
const showLibrary = ref(true)
|
||||
const handleOpenLibrary = ()=>{
|
||||
selectImages.value.init()
|
||||
}
|
||||
const handleImageSelect = (item:any)=>{
|
||||
UrlToFile(item.url,item.name).then((file:any)=>{
|
||||
// 构造符合 fileUploadChange 期望的数据结构
|
||||
const fileData = {
|
||||
file: {
|
||||
originFileObj: file, // 将 File 对象放在 originFileObj 属性中
|
||||
status: 'done'
|
||||
}
|
||||
}
|
||||
uploadRef.value.fileUploadChange(fileData)
|
||||
})
|
||||
}
|
||||
const handleShowListChange=(val:boolean)=>{
|
||||
console.log('val',val)
|
||||
showLibrary.value = !val
|
||||
}
|
||||
|
||||
const selectUplpadColor = (item:any)=>{
|
||||
colorData.selectColor = JSON.parse(JSON.stringify(item))
|
||||
}
|
||||
@@ -301,6 +342,14 @@ export default defineComponent({
|
||||
selectUplpadColor,
|
||||
setSelectColor,
|
||||
getTcxColor,
|
||||
handleOpenLibrary,
|
||||
Https,
|
||||
showLibrary,
|
||||
selectImages,
|
||||
uploadRef,
|
||||
handleImageSelect,
|
||||
handleShowListChange,
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
@@ -312,21 +361,46 @@ export default defineComponent({
|
||||
})
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.color{
|
||||
|
||||
.flex{
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.flex-column{
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.flex-align-center{
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.flex-justify-center{
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.flex-justify-between{
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.flex-justify-around{
|
||||
justify-content: space-around;
|
||||
}
|
||||
.color{
|
||||
// width: 34rem;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
// height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
row-gap: 1rem;
|
||||
overflow-y: auto;
|
||||
> .detailText{
|
||||
margin-bottom: .5rem;
|
||||
}
|
||||
> .pallet{
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
// > .detailText{
|
||||
// margin-bottom: .5rem;
|
||||
// }
|
||||
// > .pallet{
|
||||
// margin-bottom: 2rem;
|
||||
// }
|
||||
> .colorBox{
|
||||
margin-bottom: 1rem;
|
||||
// margin-bottom: 1rem;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
@@ -368,15 +442,44 @@ export default defineComponent({
|
||||
}
|
||||
> .uploadImage{
|
||||
flex-shrink: 0;
|
||||
margin-bottom: 3rem;
|
||||
// margin-bottom: 3rem;
|
||||
border: 1px dashed transparent;
|
||||
background: linear-gradient(#fff, #fff) padding-box,repeating-linear-gradient(-45deg,#fff 0,#fff 0.3em, #000 0,#000 0.6em);
|
||||
height: 10rem;
|
||||
width: 100%;
|
||||
border-radius: .5rem;
|
||||
column-gap: 2rem;
|
||||
.upload-container{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-evenly;
|
||||
align-items: center;
|
||||
background-color: #EDEDED;
|
||||
border-radius: 1rem;
|
||||
width: 7rem;
|
||||
height: 7rem;
|
||||
// row-gap: 1rem;
|
||||
&.hide{
|
||||
width: initial;
|
||||
height: initial;
|
||||
border: none;
|
||||
padding: 0;
|
||||
flex: 1;
|
||||
background-color: transparent;
|
||||
padding-left: 1rem;
|
||||
}
|
||||
.svg-btn{
|
||||
cursor: pointer;
|
||||
width: initial;
|
||||
height: initial;
|
||||
}
|
||||
:deep(.ant-upload){
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
> .colorCode{
|
||||
margin-bottom: 3rem;
|
||||
// margin-bottom: 3rem;
|
||||
> .generalModel_state{
|
||||
> .generalModel_state_item{
|
||||
width: 100%;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="palletBox">
|
||||
<div v-show="palletShow" class="color_setting_block">
|
||||
<div v-show="palletShow" class="color_setting_block" @click.stop>
|
||||
<Chrome class="chrome_color" v-model="color_"></Chrome>
|
||||
<div class="color_setting_operateSingle">
|
||||
<div class="color_setting_btn" :class="{active:!color?.gradient?.gradientShow}">{{ $t('ColorboardUpload.Single') }}</div>
|
||||
@@ -42,7 +42,7 @@
|
||||
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent,computed,ref,watch,nextTick,onMounted,toRefs, reactive} from 'vue'
|
||||
import { defineComponent,computed,ref,watch,nextTick,onMounted,onUnmounted,toRefs, reactive} from 'vue'
|
||||
import { useStore } from "vuex";
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { message,Upload} from 'ant-design-vue';
|
||||
@@ -273,7 +273,24 @@ export default defineComponent({
|
||||
}else{
|
||||
}
|
||||
}
|
||||
// 点击外部区域关闭颜色选择器
|
||||
const handleClickOutside = (event: Event) => {
|
||||
const target = event.target as HTMLElement;
|
||||
const colorSettingBlock = document.querySelector('.color_setting_block');
|
||||
const palletColo = document.querySelector('.palletColo');
|
||||
|
||||
// 如果点击的是 .palletColo 或 .color_setting_block 内部,则不关闭
|
||||
if (palletData.palletShow && colorSettingBlock &&
|
||||
!colorSettingBlock.contains(target) &&
|
||||
!palletColo?.contains(target)) {
|
||||
palletData.palletShow = false;
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(()=>{
|
||||
// 添加点击外部区域监听器
|
||||
document.addEventListener('click', handleClickOutside);
|
||||
|
||||
nextTick().then(()=>{
|
||||
const backIcon = document.createElement('div');
|
||||
backIcon.classList.add('vc-sketch-color-wrap')
|
||||
@@ -297,6 +314,11 @@ export default defineComponent({
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
onUnmounted(()=>{
|
||||
// 清理事件监听器
|
||||
document.removeEventListener('click', handleClickOutside);
|
||||
})
|
||||
return{
|
||||
...toRefs(palletData),
|
||||
...toRefs(getpalletListDom),
|
||||
|
||||
@@ -44,7 +44,7 @@ import { rgbaToHex } from "@/tool/util"
|
||||
export default defineComponent({
|
||||
components:{
|
||||
},
|
||||
emits:['selectUplpadColor'],
|
||||
emits:['selectUplpadColor','deleteColor','selectFile'],
|
||||
setup(props,{emit}) {
|
||||
const {t} = useI18n();
|
||||
const store = useStore();
|
||||
@@ -63,6 +63,8 @@ export default defineComponent({
|
||||
})
|
||||
|
||||
const fileUploadChange = (data:any)=>{
|
||||
emit('selectFile')
|
||||
console.log('fileUploadChange',data)
|
||||
let file:any = data.file
|
||||
let fileData = file.originFileObj
|
||||
var reader = new FileReader();
|
||||
@@ -157,6 +159,7 @@ export default defineComponent({
|
||||
const colorDeleteFile = ()=>{
|
||||
colorUpload.uploadList[colorUpload.selectDetail.id] = []
|
||||
colorUpload.colorList[colorUpload.selectDetail.id] = []
|
||||
emit('deleteColor')
|
||||
}
|
||||
return{
|
||||
...toRefs(colorUpload),
|
||||
@@ -178,8 +181,8 @@ export default defineComponent({
|
||||
<style lang="less" scoped>
|
||||
.upload{
|
||||
// width: 34rem;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
// width: 100%;
|
||||
// height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
:deep(.ant-upload-picture-card-wrapper){
|
||||
@@ -201,7 +204,7 @@ export default defineComponent({
|
||||
}
|
||||
.upload_tip_block{
|
||||
i{
|
||||
font-size: 4rem;
|
||||
font-size: 2rem;
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,10 +122,11 @@ export default defineComponent({
|
||||
padding: 1rem;
|
||||
text-align: center;
|
||||
border-radius: .5rem;
|
||||
// border: 1px dashed #202020;
|
||||
border: 1px dashed transparent;
|
||||
border: 1px solid #000;
|
||||
// border: 1px dashed transparent;
|
||||
border-radius: 1.5rem;
|
||||
background: linear-gradient(#fff, #fff) padding-box,repeating-linear-gradient(-45deg,#fff 0,#fff 0.3em, #000 0,#000 0.6em);
|
||||
margin-bottom: 3rem;
|
||||
margin-bottom: 1.4rem;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
overflow: hidden;
|
||||
|
||||
@@ -70,10 +70,12 @@ export default defineComponent({
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.detailLeft{
|
||||
width: 34rem;
|
||||
// width: 34rem;
|
||||
// width: 100%;
|
||||
height: 100%;
|
||||
// height: 100%;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
flex-direction: column;
|
||||
}
|
||||
</style>
|
||||
@@ -100,11 +100,12 @@ export default defineComponent({
|
||||
padding: 1rem 0;
|
||||
text-align: center;
|
||||
border-radius: .5rem;
|
||||
// border: 1px dashed #202020;
|
||||
border: 1px dashed transparent;
|
||||
border: 1px solid #000;
|
||||
// border: 1px dashed transparent;
|
||||
border-radius: 1.5rem;
|
||||
position: relative;
|
||||
background: linear-gradient(#fff, #fff) padding-box,repeating-linear-gradient(-45deg,#fff 0,#fff 0.3em, #000 0,#000 0.6em);
|
||||
margin-bottom: 3rem;
|
||||
margin-bottom: 1.4rem;
|
||||
> img{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
@@ -107,9 +107,9 @@ export default defineComponent({
|
||||
align-content: flex-start;
|
||||
&::-webkit-scrollbar{display: none;}
|
||||
> .content_img_item{
|
||||
width: calc((50% - 1rem));
|
||||
> .content_img_item_block{
|
||||
width: calc((34rem - 2rem) / 2);
|
||||
height: calc((34rem - 2rem) / 2);
|
||||
aspect-ratio: 1/1;
|
||||
position: relative;
|
||||
margin-bottom: 2rem;
|
||||
|
||||
@@ -121,16 +121,6 @@ export default defineComponent({
|
||||
}
|
||||
}
|
||||
}
|
||||
> .material_content_list_loding{
|
||||
width: 100%;
|
||||
height: calc((34rem - 2rem) / 2);
|
||||
}
|
||||
> .upload_item{
|
||||
width: calc((34rem - 2rem) / 2);
|
||||
height: calc((34rem - 2rem) / 2);
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
v-model:value="designType"
|
||||
:options="(designTypeList)"
|
||||
@change="handleChange"
|
||||
style="width:100%"
|
||||
style="width:100%; font-size: 1.4rem;"
|
||||
size="large"
|
||||
:fieldNames="{ label: 'name', value: 'value' }"
|
||||
>
|
||||
@@ -23,7 +23,7 @@
|
||||
v-model:value="mannequinData.system"
|
||||
:options="systemList"
|
||||
@change="handleChange"
|
||||
style="width:100%"
|
||||
style="width:100%; font-size: 1.4rem;"
|
||||
size="large"
|
||||
:fieldNames="{ label: 'name', value: 'value' }"
|
||||
>
|
||||
@@ -41,7 +41,7 @@
|
||||
v-model:value="mannequinData.style"
|
||||
:options="mannequinStyle"
|
||||
@change="handleChange"
|
||||
style="width:100%"
|
||||
style="width:100%; font-size: 1.4rem;"
|
||||
size="large"
|
||||
:fieldNames="{ label: 'name', value: 'value' }"
|
||||
>
|
||||
@@ -58,7 +58,7 @@
|
||||
v-model:value="mannequinData.ageGroup"
|
||||
:options="ageGroupList"
|
||||
@change="handleChange"
|
||||
style="width:100%"
|
||||
style="width:100%; font-size: 1.4rem;"
|
||||
size="large"
|
||||
:fieldNames="{ label: 'name', value: 'value' }"
|
||||
>
|
||||
@@ -75,7 +75,7 @@
|
||||
v-model:value="mannequinData.sex"
|
||||
:options="sexList"
|
||||
@change="handleChange"
|
||||
style="width:100%"
|
||||
style="width:100%; font-size: 1.4rem;"
|
||||
size="large"
|
||||
:fieldNames="{ label: 'name', value: 'value' }"
|
||||
>
|
||||
@@ -333,6 +333,9 @@ export default defineComponent({
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
> .search_input{
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
}
|
||||
> .generalModel_state_item:last-child{
|
||||
// margin-top: 2rem;
|
||||
@@ -347,11 +350,11 @@ export default defineComponent({
|
||||
margin-top: 1rem;
|
||||
justify-content: space-between;
|
||||
align-content: flex-start;
|
||||
&::-webkit-scrollbar{display: none;}
|
||||
// &::-webkit-scrollbar{display: none;}
|
||||
> .content_img_item{
|
||||
width: calc((50% - 1rem));
|
||||
> .content_img_item_block{
|
||||
width: calc((34rem - 2rem) / 2);
|
||||
height: calc((34rem - 2rem) / 2);
|
||||
aspect-ratio: 1/1;
|
||||
position: relative;
|
||||
margin-bottom: 2rem;
|
||||
cursor: pointer;
|
||||
@@ -364,7 +367,7 @@ export default defineComponent({
|
||||
}
|
||||
> .material_content_list_loding{
|
||||
width: 100%;
|
||||
height: calc((34rem - 2rem) / 2);
|
||||
aspect-ratio: 1/1;
|
||||
overflow: hidden;
|
||||
> img{
|
||||
width: 100%;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="selectList">
|
||||
<div class="selectList_header">
|
||||
<div class="selectList_header" :class="{'element': type == 'element'}">
|
||||
<div class="switch_type_list" v-if="type != 'element'">
|
||||
<div
|
||||
@click.stop="openCurrent()"
|
||||
@@ -161,10 +161,16 @@ export default defineComponent({
|
||||
height: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-radius: 1.5rem;
|
||||
border: 1px solid #000;
|
||||
padding: 1rem;
|
||||
> .selectList_header{
|
||||
margin-bottom: 2.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
&.element{
|
||||
margin-bottom: 0rem;
|
||||
}
|
||||
> .switch_type_list{
|
||||
display: flex;
|
||||
> .switch_type_item:last-child{
|
||||
@@ -173,8 +179,11 @@ export default defineComponent({
|
||||
> .switch_type_item{
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
margin-right: 6.5rem;
|
||||
margin-right: 4rem;
|
||||
font-size: 1.8rem;
|
||||
> .detailText{
|
||||
font-size: 1.6rem;
|
||||
}
|
||||
}
|
||||
> .switch_type_item::before {
|
||||
position: absolute;
|
||||
|
||||
@@ -200,9 +200,9 @@ export default defineComponent({
|
||||
align-content: flex-start;
|
||||
&::-webkit-scrollbar{display: none;}
|
||||
> .content_img_item{
|
||||
width: calc((50% - 1rem));
|
||||
> .content_img_item_block{
|
||||
width: calc((34rem - 2rem) / 2);
|
||||
height: calc((34rem - 2rem) / 2);
|
||||
aspect-ratio: 1/1;
|
||||
position: relative;
|
||||
margin-bottom: 2rem;
|
||||
|
||||
@@ -216,11 +216,11 @@ export default defineComponent({
|
||||
}
|
||||
> .material_content_list_loding{
|
||||
width: 100%;
|
||||
height: calc((34rem - 2rem) / 2);
|
||||
aspect-ratio: 1/1;
|
||||
}
|
||||
> .upload_item{
|
||||
width: calc((34rem - 2rem) / 2);
|
||||
height: calc((34rem - 2rem) / 2);
|
||||
width: calc((50% - 1rem));
|
||||
aspect-ratio: 1/1;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
@@ -262,9 +262,10 @@ import sketchCategory from "@/component/HomePage/sketchCategory.vue";
|
||||
align-content: flex-start;
|
||||
&::-webkit-scrollbar{display: none;}
|
||||
> .content_img_item{
|
||||
width: calc((50% - 1rem));
|
||||
> .content_img_item_block{
|
||||
width: calc((34rem - 2rem) / 2);
|
||||
height: calc((34rem - 2rem) / 2);
|
||||
width: 100%;
|
||||
aspect-ratio: 1/1;
|
||||
position: relative;
|
||||
margin-bottom: 2rem;
|
||||
margin: 1rem;
|
||||
@@ -279,11 +280,11 @@ import sketchCategory from "@/component/HomePage/sketchCategory.vue";
|
||||
}
|
||||
> .material_content_list_loding{
|
||||
width: 100%;
|
||||
height: calc((34rem - 2rem) / 2);
|
||||
aspect-ratio: 1/1;
|
||||
}
|
||||
> .upload_item{
|
||||
width: calc((34rem - 2rem) / 2);
|
||||
height: calc((34rem - 2rem) / 2);
|
||||
width: calc((50% - 1rem));
|
||||
aspect-ratio: 1/1;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.upload{
|
||||
|
||||
@@ -145,9 +145,9 @@ export default defineComponent({
|
||||
align-content: flex-start;
|
||||
&::-webkit-scrollbar{display: none;}
|
||||
> .content_img_item{
|
||||
width: calc((50% - 1rem));
|
||||
> .content_img_item_block{
|
||||
width: calc((34rem - 2rem) / 2);
|
||||
height: calc((34rem - 2rem) / 2);
|
||||
aspect-ratio: 1/1;
|
||||
position: relative;
|
||||
margin-bottom: 2rem;
|
||||
|
||||
@@ -174,11 +174,11 @@ export default defineComponent({
|
||||
}
|
||||
> .material_content_list_loding{
|
||||
width: 100%;
|
||||
height: calc((34rem - 2rem) / 2);
|
||||
aspect-ratio: 1/1;
|
||||
}
|
||||
> .upload_item{
|
||||
width: calc((34rem - 2rem) / 2);
|
||||
height: calc((34rem - 2rem) / 2);
|
||||
width: calc((50% - 1rem));
|
||||
aspect-ratio: 1/1;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.upload{
|
||||
|
||||
@@ -120,11 +120,11 @@ export default defineComponent({
|
||||
height: 23.5rem;
|
||||
padding: 1rem;
|
||||
text-align: center;
|
||||
border-radius: .5rem;
|
||||
// border: 1px dashed #202020;
|
||||
border: 1px dashed transparent;
|
||||
border: 1px solid #000;
|
||||
// border: 1px dashed transparent;
|
||||
border-radius: 1.5rem;
|
||||
background: linear-gradient(#fff, #fff) padding-box,repeating-linear-gradient(-45deg,#fff 0,#fff 0.3em, #000 0,#000 0.6em);
|
||||
margin-bottom: 3rem;
|
||||
margin-bottom: 1.4rem;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
overflow: hidden;
|
||||
|
||||
@@ -126,11 +126,12 @@ export default defineComponent({
|
||||
padding: 1rem 0;
|
||||
text-align: center;
|
||||
border-radius: .5rem;
|
||||
// border: 1px dashed #202020;
|
||||
border: 1px dashed transparent;
|
||||
border: 1px solid #000;
|
||||
// border: 1px dashed transparent;
|
||||
border-radius: 1.5rem;
|
||||
position: relative;
|
||||
background: linear-gradient(#fff, #fff) padding-box,repeating-linear-gradient(-45deg,#fff 0,#fff 0.3em, #000 0,#000 0.6em);
|
||||
margin-bottom: 3rem;
|
||||
margin-bottom: 1.4rem;
|
||||
> img{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||