diff --git a/.env.dev_build b/.env.dev_build index da2a9a20..9de2530a 100644 --- a/.env.dev_build +++ b/.env.dev_build @@ -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' diff --git a/.env.test b/.env.test index ebe37860..cc8ff50b 100644 --- a/.env.test +++ b/.env.test @@ -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' diff --git a/.gitignore b/.gitignore index 118a6b88..61bc8e64 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,4 @@ dist.rar *.sln *.sw? .eslintrc-auto-import.json +components.d.ts diff --git a/components.d.ts b/components.d.ts deleted file mode 100644 index cec5253a..00000000 --- a/components.d.ts +++ /dev/null @@ -1,38 +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'] - AConfigProvider: typeof import('ant-design-vue/es')['ConfigProvider'] - 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'] - ATabPane: typeof import('ant-design-vue/es')['TabPane'] - ATabs: typeof import('ant-design-vue/es')['Tabs'] - AUpload: typeof import('ant-design-vue/es')['Upload'] - ElCascader: typeof import('element-plus/es')['ElCascader'] - ElLoading: typeof import('element-plus/es')['ElLoading'] - ElPagination: typeof import('element-plus/es')['ElPagination'] - ElTable: typeof import('element-plus/es')['ElTable'] - ElTableColumn: typeof import('element-plus/es')['ElTableColumn'] - RouterLink: typeof import('vue-router')['RouterLink'] - RouterView: typeof import('vue-router')['RouterView'] - } -} diff --git a/dist.7z b/dist.7z index 704ed151..866b68e7 100644 Binary files a/dist.7z and b/dist.7z differ diff --git a/package-lock.json b/package-lock.json index bd605983..0e42a09e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -35,7 +35,8 @@ "vue-i18n": "^9.6.1", "vue-router": "^4.0.3", "vuedraggable": "^4.1.0", - "vuex": "^4.0.0" + "vuex": "^4.0.0", + "x-sender": "^1.1.6" }, "devDependencies": { "@types/three": "^0.174.0", @@ -10106,6 +10107,12 @@ } } }, + "node_modules/x-sender": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/x-sender/-/x-sender-1.1.6.tgz", + "integrity": "sha512-es24YnTY1+g3TdDVrEgRVW8uW2nYPyHjQveBgZxk8JrB7809yd8AkYptrLgqL1trpUZtMILVW+2GIoB0V5HfVQ==", + "license": "MIT" + }, "node_modules/xml-name-validator": { "version": "4.0.0", "resolved": "https://registry.npmmirror.com/xml-name-validator/-/xml-name-validator-4.0.0.tgz", diff --git a/package.json b/package.json index 63b09be9..962ae9e0 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,8 @@ "vue-i18n": "^9.6.1", "vue-router": "^4.0.3", "vuedraggable": "^4.1.0", - "vuex": "^4.0.0" + "vuex": "^4.0.0", + "x-sender": "^1.1.6" }, "devDependencies": { "@types/three": "^0.174.0", @@ -105,4 +106,4 @@ "not dead", "not ie 11" ] -} \ No newline at end of file +} diff --git a/public/sketch_bar_chart.html b/public/sketch_bar_chart.html new file mode 100644 index 00000000..91135472 --- /dev/null +++ b/public/sketch_bar_chart.html @@ -0,0 +1,427 @@ + + + + + style category + + + + + + +
+
+
+

style category

+ +
+

1. ALL

+
+ +
+
+ +
+

2. Male

+
+ +
+
+ +
+

3. Female

+
+ +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/src/assets/iconfont2/demo.css b/src/assets/iconfont2/demo.css new file mode 100644 index 00000000..a67054a0 --- /dev/null +++ b/src/assets/iconfont2/demo.css @@ -0,0 +1,539 @@ +/* Logo 字体 */ +@font-face { + font-family: "iconfont logo"; + src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834'); + src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'), + url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'), + url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'), + url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg'); +} + +.logo { + font-family: "iconfont logo"; + font-size: 160px; + font-style: normal; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +/* tabs */ +.nav-tabs { + position: relative; +} + +.nav-tabs .nav-more { + position: absolute; + right: 0; + bottom: 0; + height: 42px; + line-height: 42px; + color: #666; +} + +#tabs { + border-bottom: 1px solid #eee; +} + +#tabs li { + cursor: pointer; + width: 100px; + height: 40px; + line-height: 40px; + text-align: center; + font-size: 16px; + border-bottom: 2px solid transparent; + position: relative; + z-index: 1; + margin-bottom: -1px; + color: #666; +} + + +#tabs .active { + border-bottom-color: #f00; + color: #222; +} + +.tab-container .content { + display: none; +} + +/* 页面布局 */ +.main { + padding: 30px 100px; + width: 960px; + margin: 0 auto; +} + +.main .logo { + color: #333; + text-align: left; + margin-bottom: 30px; + line-height: 1; + height: 110px; + margin-top: -50px; + overflow: hidden; + *zoom: 1; +} + +.main .logo a { + font-size: 160px; + color: #333; +} + +.helps { + margin-top: 40px; +} + +.helps pre { + padding: 20px; + margin: 10px 0; + border: solid 1px #e7e1cd; + background-color: #fffdef; + overflow: auto; +} + +.icon_lists { + width: 100% !important; + overflow: hidden; + *zoom: 1; +} + +.icon_lists li { + width: 100px; + margin-bottom: 10px; + margin-right: 20px; + text-align: center; + list-style: none !important; + cursor: default; +} + +.icon_lists li .code-name { + line-height: 1.2; +} + +.icon_lists .icon { + display: block; + height: 100px; + line-height: 100px; + font-size: 42px; + margin: 10px auto; + color: #333; + -webkit-transition: font-size 0.25s linear, width 0.25s linear; + -moz-transition: font-size 0.25s linear, width 0.25s linear; + transition: font-size 0.25s linear, width 0.25s linear; +} + +.icon_lists .icon:hover { + font-size: 100px; +} + +.icon_lists .svg-icon { + /* 通过设置 font-size 来改变图标大小 */ + width: 1em; + /* 图标和文字相邻时,垂直对齐 */ + vertical-align: -0.15em; + /* 通过设置 color 来改变 SVG 的颜色/fill */ + fill: currentColor; + /* path 和 stroke 溢出 viewBox 部分在 IE 下会显示 + normalize.css 中也包含这行 */ + overflow: hidden; +} + +.icon_lists li .name, +.icon_lists li .code-name { + color: #666; +} + +/* markdown 样式 */ +.markdown { + color: #666; + font-size: 14px; + line-height: 1.8; +} + +.highlight { + line-height: 1.5; +} + +.markdown img { + vertical-align: middle; + max-width: 100%; +} + +.markdown h1 { + color: #404040; + font-weight: 500; + line-height: 40px; + margin-bottom: 24px; +} + +.markdown h2, +.markdown h3, +.markdown h4, +.markdown h5, +.markdown h6 { + color: #404040; + margin: 1.6em 0 0.6em 0; + font-weight: 500; + clear: both; +} + +.markdown h1 { + font-size: 28px; +} + +.markdown h2 { + font-size: 22px; +} + +.markdown h3 { + font-size: 16px; +} + +.markdown h4 { + font-size: 14px; +} + +.markdown h5 { + font-size: 12px; +} + +.markdown h6 { + font-size: 12px; +} + +.markdown hr { + height: 1px; + border: 0; + background: #e9e9e9; + margin: 16px 0; + clear: both; +} + +.markdown p { + margin: 1em 0; +} + +.markdown>p, +.markdown>blockquote, +.markdown>.highlight, +.markdown>ol, +.markdown>ul { + width: 80%; +} + +.markdown ul>li { + list-style: circle; +} + +.markdown>ul li, +.markdown blockquote ul>li { + margin-left: 20px; + padding-left: 4px; +} + +.markdown>ul li p, +.markdown>ol li p { + margin: 0.6em 0; +} + +.markdown ol>li { + list-style: decimal; +} + +.markdown>ol li, +.markdown blockquote ol>li { + margin-left: 20px; + padding-left: 4px; +} + +.markdown code { + margin: 0 3px; + padding: 0 5px; + background: #eee; + border-radius: 3px; +} + +.markdown strong, +.markdown b { + font-weight: 600; +} + +.markdown>table { + border-collapse: collapse; + border-spacing: 0px; + empty-cells: show; + border: 1px solid #e9e9e9; + width: 95%; + margin-bottom: 24px; +} + +.markdown>table th { + white-space: nowrap; + color: #333; + font-weight: 600; +} + +.markdown>table th, +.markdown>table td { + border: 1px solid #e9e9e9; + padding: 8px 16px; + text-align: left; +} + +.markdown>table th { + background: #F7F7F7; +} + +.markdown blockquote { + font-size: 90%; + color: #999; + border-left: 4px solid #e9e9e9; + padding-left: 0.8em; + margin: 1em 0; +} + +.markdown blockquote p { + margin: 0; +} + +.markdown .anchor { + opacity: 0; + transition: opacity 0.3s ease; + margin-left: 8px; +} + +.markdown .waiting { + color: #ccc; +} + +.markdown h1:hover .anchor, +.markdown h2:hover .anchor, +.markdown h3:hover .anchor, +.markdown h4:hover .anchor, +.markdown h5:hover .anchor, +.markdown h6:hover .anchor { + opacity: 1; + display: inline-block; +} + +.markdown>br, +.markdown>p>br { + clear: both; +} + + +.hljs { + display: block; + background: white; + padding: 0.5em; + color: #333333; + overflow-x: auto; +} + +.hljs-comment, +.hljs-meta { + color: #969896; +} + +.hljs-string, +.hljs-variable, +.hljs-template-variable, +.hljs-strong, +.hljs-emphasis, +.hljs-quote { + color: #df5000; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-type { + color: #a71d5d; +} + +.hljs-literal, +.hljs-symbol, +.hljs-bullet, +.hljs-attribute { + color: #0086b3; +} + +.hljs-section, +.hljs-name { + color: #63a35c; +} + +.hljs-tag { + color: #333333; +} + +.hljs-title, +.hljs-attr, +.hljs-selector-id, +.hljs-selector-class, +.hljs-selector-attr, +.hljs-selector-pseudo { + color: #795da3; +} + +.hljs-addition { + color: #55a532; + background-color: #eaffea; +} + +.hljs-deletion { + color: #bd2c00; + background-color: #ffecec; +} + +.hljs-link { + text-decoration: underline; +} + +/* 代码高亮 */ +/* PrismJS 1.15.0 +https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */ +/** + * prism.js default theme for JavaScript, CSS and HTML + * Based on dabblet (http://dabblet.com) + * @author Lea Verou + */ +code[class*="language-"], +pre[class*="language-"] { + color: black; + background: none; + text-shadow: 0 1px white; + font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; + text-align: left; + white-space: pre; + word-spacing: normal; + word-break: normal; + word-wrap: normal; + line-height: 1.5; + + -moz-tab-size: 4; + -o-tab-size: 4; + tab-size: 4; + + -webkit-hyphens: none; + -moz-hyphens: none; + -ms-hyphens: none; + hyphens: none; +} + +pre[class*="language-"]::-moz-selection, +pre[class*="language-"] ::-moz-selection, +code[class*="language-"]::-moz-selection, +code[class*="language-"] ::-moz-selection { + text-shadow: none; + background: #b3d4fc; +} + +pre[class*="language-"]::selection, +pre[class*="language-"] ::selection, +code[class*="language-"]::selection, +code[class*="language-"] ::selection { + text-shadow: none; + background: #b3d4fc; +} + +@media print { + + code[class*="language-"], + pre[class*="language-"] { + text-shadow: none; + } +} + +/* Code blocks */ +pre[class*="language-"] { + padding: 1em; + margin: .5em 0; + overflow: auto; +} + +:not(pre)>code[class*="language-"], +pre[class*="language-"] { + background: #f5f2f0; +} + +/* Inline code */ +:not(pre)>code[class*="language-"] { + padding: .1em; + border-radius: .3em; + white-space: normal; +} + +.token.comment, +.token.prolog, +.token.doctype, +.token.cdata { + color: slategray; +} + +.token.punctuation { + color: #999; +} + +.namespace { + opacity: .7; +} + +.token.property, +.token.tag, +.token.boolean, +.token.number, +.token.constant, +.token.symbol, +.token.deleted { + color: #905; +} + +.token.selector, +.token.attr-name, +.token.string, +.token.char, +.token.builtin, +.token.inserted { + color: #690; +} + +.token.operator, +.token.entity, +.token.url, +.language-css .token.string, +.style .token.string { + color: #9a6e3a; + background: hsla(0, 0%, 100%, .5); +} + +.token.atrule, +.token.attr-value, +.token.keyword { + color: #07a; +} + +.token.function, +.token.class-name { + color: #DD4A68; +} + +.token.regex, +.token.important, +.token.variable { + color: #e90; +} + +.token.important, +.token.bold { + font-weight: bold; +} + +.token.italic { + font-style: italic; +} + +.token.entity { + cursor: help; +} diff --git a/src/assets/iconfont2/demo_index.html b/src/assets/iconfont2/demo_index.html new file mode 100644 index 00000000..86fd4fdc --- /dev/null +++ b/src/assets/iconfont2/demo_index.html @@ -0,0 +1,970 @@ + + + + + iconfont Demo + + + + + + + + + + + + + +
+

+ + +

+ +
+
+
    + +
  • + +
    裁剪
    +
    &#xe650;
    +
  • + +
  • + +
    角度
    +
    &#xe60a;
    +
  • + +
  • + +
    水平翻转
    +
    &#xe69e;
    +
  • + +
  • + +
    垂直翻转
    +
    &#xec60;
    +
  • + +
  • + +
    clothes
    +
    &#xe8d1;
    +
  • + +
  • + +
    材质
    +
    &#xe647;
    +
  • + +
  • + +
    IC-液化
    +
    &#xe61b;
    +
  • + +
  • + +
    上一层
    +
    &#xe751;
    +
  • + +
  • + +
    上一层
    +
    &#xe604;
    +
  • + +
  • + +
    下一层
    +
    &#xe68a;
    +
  • + +
  • + +
    上一层
    +
    &#xe68b;
    +
  • + +
  • + +
    审批
    +
    &#xe6a1;
    +
  • + +
  • + +
    用户
    +
    &#xe617;
    +
  • + +
  • + +
    使用次数
    +
    &#xe601;
    +
  • + +
  • + +
    下拉
    +
    &#xe634;
    +
  • + +
  • + +
    编辑
    +
    &#xe600;
    +
  • + +
  • + +
    圆形
    +
    &#xe64f;
    +
  • + +
  • + +
    三角形
    +
    &#xe615;
    +
  • + +
  • + +
    图层
    +
    &#xe632;
    +
  • + +
  • + +
    平移
    +
    &#xe616;
    +
  • + +
  • + +
    橡皮
    +
    &#xe67b;
    +
  • + +
  • + +
    tx-fill-椭圆形
    +
    &#xe64c;
    +
  • + +
  • + +
    直线
    +
    &#xe602;
    +
  • + +
  • + +
    线
    +
    &#xec5f;
    +
  • + +
  • + +
    正方形
    +
    &#xea6f;
    +
  • + +
  • + +
    图层
    +
    &#xe62d;
    +
  • + +
  • + +
    点位
    +
    &#xe685;
    +
  • + +
  • + +
    并集
    +
    &#xe620;
    +
  • + +
  • + +
    并集
    +
    &#xe668;
    +
  • + +
  • + +
    标签
    +
    &#xe603;
    +
  • + +
  • + +
    语言
    +
    &#xe85f;
    +
  • + +
  • + +
    撤销 返回 撤回 上一步
    +
    &#xe626;
    +
  • + +
  • + +
    撤销 返回 撤回 上一步
    +
    &#xe609;
    +
  • + +
  • + +
    外套_长款外套1@1x
    +
    &#xe66c;
    +
  • + +
+
+

Unicode 引用

+
+ +

Unicode 是字体在网页端最原始的应用方式,特点是:

+
    +
  • 支持按字体的方式去动态调整图标大小,颜色等等。
  • +
  • 默认情况下不支持多色,直接添加多色图标会自动去色。
  • +
+
+

注意:新版 iconfont 支持两种方式引用多色图标:SVG symbol 引用方式和彩色字体图标模式。(使用彩色字体图标需要在「编辑项目」中开启「彩色」选项后并重新生成。)

+
+

Unicode 使用步骤如下:

+

第一步:拷贝项目下面生成的 @font-face

+
@font-face {
+  font-family: 'iconfont';
+  src: url('iconfont.woff2?t=1762934152017') format('woff2'),
+       url('iconfont.woff?t=1762934152017') format('woff'),
+       url('iconfont.ttf?t=1762934152017') format('truetype');
+}
+
+

第二步:定义使用 iconfont 的样式

+
.iconfont {
+  font-family: "iconfont" !important;
+  font-size: 16px;
+  font-style: normal;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}
+
+

第三步:挑选相应图标并获取字体编码,应用于页面

+
+<span class="iconfont">&#x33;</span>
+
+
+

"iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。

+
+
+
+
+
    + +
  • + +
    + 裁剪 +
    +
    .icon-caijian +
    +
  • + +
  • + +
    + 角度 +
    +
    .icon-angle +
    +
  • + +
  • + +
    + 水平翻转 +
    +
    .icon-flip-horizontal +
    +
  • + +
  • + +
    + 垂直翻转 +
    +
    .icon-flip-vertical +
    +
  • + +
  • + +
    + clothes +
    +
    .icon-clothes +
    +
  • + +
  • + +
    + 材质 +
    +
    .icon-caizhi +
    +
  • + +
  • + +
    + IC-液化 +
    +
    .icon-IC-yehua +
    +
  • + +
  • + +
    + 上一层 +
    +
    .icon-shangyiceng +
    +
  • + +
  • + +
    + 上一层 +
    +
    .icon-shangyiceng1 +
    +
  • + +
  • + +
    + 下一层 +
    +
    .icon-xiayiceng +
    +
  • + +
  • + +
    + 上一层 +
    +
    .icon-shangyiceng2 +
    +
  • + +
  • + +
    + 审批 +
    +
    .icon-shenpi +
    +
  • + +
  • + +
    + 用户 +
    +
    .icon-yonghu +
    +
  • + +
  • + +
    + 使用次数 +
    +
    .icon-usetime +
    +
  • + +
  • + +
    + 下拉 +
    +
    .icon-xiala +
    +
  • + +
  • + +
    + 编辑 +
    +
    .icon-bianji +
    +
  • + +
  • + +
    + 圆形 +
    +
    .icon-circle +
    +
  • + +
  • + +
    + 三角形 +
    +
    .icon-sanjiaoxing +
    +
  • + +
  • + +
    + 图层 +
    +
    .icon-tuceng +
    +
  • + +
  • + +
    + 平移 +
    +
    .icon-move +
    +
  • + +
  • + +
    + 橡皮 +
    +
    .icon-xiangpi_huaban1 +
    +
  • + +
  • + +
    + tx-fill-椭圆形 +
    +
    .icon-tx-fill-tuoyuanxing +
    +
  • + +
  • + +
    + 直线 +
    +
    .icon-zhixian +
    +
  • + +
  • + +
    + 线 +
    +
    .icon-xian +
    +
  • + +
  • + +
    + 正方形 +
    +
    .icon-checkbox-full +
    +
  • + +
  • + +
    + 图层 +
    +
    .icon-tuceng1 +
    +
  • + +
  • + +
    + 点位 +
    +
    .icon-dianwei +
    +
  • + +
  • + +
    + 并集 +
    +
    .icon-bingji +
    +
  • + +
  • + +
    + 并集 +
    +
    .icon-bingji1 +
    +
  • + +
  • + +
    + 标签 +
    +
    .icon-biaoqian +
    +
  • + +
  • + +
    + 语言 +
    +
    .icon-yuyan +
    +
  • + +
  • + +
    + 撤销 返回 撤回 上一步 +
    +
    .icon-fanchehui +
    +
  • + +
  • + +
    + 撤销 返回 撤回 上一步 +
    +
    .icon-chehui +
    +
  • + +
  • + +
    + 外套_长款外套1@1x +
    +
    .icon-a-waitao_changkuanwaitao11x +
    +
  • + +
+
+

font-class 引用

+
+ +

font-class 是 Unicode 使用方式的一种变种,主要是解决 Unicode 书写不直观,语意不明确的问题。

+

与 Unicode 使用方式相比,具有如下特点:

+
    +
  • 相比于 Unicode 语意明确,书写更直观。可以很容易分辨这个 icon 是什么。
  • +
  • 因为使用 class 来定义图标,所以当要替换图标时,只需要修改 class 里面的 Unicode 引用。
  • +
+

使用步骤如下:

+

第一步:引入项目下面生成的 fontclass 代码:

+
<link rel="stylesheet" href="./iconfont.css">
+
+

第二步:挑选相应图标并获取类名,应用于页面:

+
<span class="iconfont icon-xxx"></span>
+
+
+

" + iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。

+
+
+
+
+
    + +
  • + +
    裁剪
    +
    #icon-caijian
    +
  • + +
  • + +
    角度
    +
    #icon-angle
    +
  • + +
  • + +
    水平翻转
    +
    #icon-flip-horizontal
    +
  • + +
  • + +
    垂直翻转
    +
    #icon-flip-vertical
    +
  • + +
  • + +
    clothes
    +
    #icon-clothes
    +
  • + +
  • + +
    材质
    +
    #icon-caizhi
    +
  • + +
  • + +
    IC-液化
    +
    #icon-IC-yehua
    +
  • + +
  • + +
    上一层
    +
    #icon-shangyiceng
    +
  • + +
  • + +
    上一层
    +
    #icon-shangyiceng1
    +
  • + +
  • + +
    下一层
    +
    #icon-xiayiceng
    +
  • + +
  • + +
    上一层
    +
    #icon-shangyiceng2
    +
  • + +
  • + +
    审批
    +
    #icon-shenpi
    +
  • + +
  • + +
    用户
    +
    #icon-yonghu
    +
  • + +
  • + +
    使用次数
    +
    #icon-usetime
    +
  • + +
  • + +
    下拉
    +
    #icon-xiala
    +
  • + +
  • + +
    编辑
    +
    #icon-bianji
    +
  • + +
  • + +
    圆形
    +
    #icon-circle
    +
  • + +
  • + +
    三角形
    +
    #icon-sanjiaoxing
    +
  • + +
  • + +
    图层
    +
    #icon-tuceng
    +
  • + +
  • + +
    平移
    +
    #icon-move
    +
  • + +
  • + +
    橡皮
    +
    #icon-xiangpi_huaban1
    +
  • + +
  • + +
    tx-fill-椭圆形
    +
    #icon-tx-fill-tuoyuanxing
    +
  • + +
  • + +
    直线
    +
    #icon-zhixian
    +
  • + +
  • + +
    线
    +
    #icon-xian
    +
  • + +
  • + +
    正方形
    +
    #icon-checkbox-full
    +
  • + +
  • + +
    图层
    +
    #icon-tuceng1
    +
  • + +
  • + +
    点位
    +
    #icon-dianwei
    +
  • + +
  • + +
    并集
    +
    #icon-bingji
    +
  • + +
  • + +
    并集
    +
    #icon-bingji1
    +
  • + +
  • + +
    标签
    +
    #icon-biaoqian
    +
  • + +
  • + +
    语言
    +
    #icon-yuyan
    +
  • + +
  • + +
    撤销 返回 撤回 上一步
    +
    #icon-fanchehui
    +
  • + +
  • + +
    撤销 返回 撤回 上一步
    +
    #icon-chehui
    +
  • + +
  • + +
    外套_长款外套1@1x
    +
    #icon-a-waitao_changkuanwaitao11x
    +
  • + +
+
+

Symbol 引用

+
+ +

这是一种全新的使用方式,应该说这才是未来的主流,也是平台目前推荐的用法。相关介绍可以参考这篇文章 + 这种用法其实是做了一个 SVG 的集合,与另外两种相比具有如下特点:

+
    +
  • 支持多色图标了,不再受单色限制。
  • +
  • 通过一些技巧,支持像字体那样,通过 font-size, color 来调整样式。
  • +
  • 兼容性较差,支持 IE9+,及现代浏览器。
  • +
  • 浏览器渲染 SVG 的性能一般,还不如 png。
  • +
+

使用步骤如下:

+

第一步:引入项目下面生成的 symbol 代码:

+
<script src="./iconfont.js"></script>
+
+

第二步:加入通用 CSS 代码(引入一次就行):

+
<style>
+.icon {
+  width: 1em;
+  height: 1em;
+  vertical-align: -0.15em;
+  fill: currentColor;
+  overflow: hidden;
+}
+</style>
+
+

第三步:挑选相应图标并获取类名,应用于页面:

+
<svg class="icon" aria-hidden="true">
+  <use xlink:href="#icon-xxx"></use>
+</svg>
+
+
+
+ +
+
+ + + diff --git a/src/assets/iconfont2/iconfont.css b/src/assets/iconfont2/iconfont.css index 1aba4c42..53b663ea 100644 --- a/src/assets/iconfont2/iconfont.css +++ b/src/assets/iconfont2/iconfont.css @@ -1,18 +1,38 @@ @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=1762934152017') format('woff2'), + url('iconfont.woff?t=1762934152017') format('woff'), + url('iconfont.ttf?t=1762934152017') format('truetype'); } .iconfont { font-family: "iconfont" !important; - font-size: 1.8rem; + font-size: 16px; font-style: normal; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } +.icon-caijian:before { + content: "\e650"; +} + +.icon-angle:before { + content: "\e60a"; +} + +.icon-flip-horizontal:before { + content: "\e69e"; +} + +.icon-flip-vertical:before { + content: "\ec60"; +} + +.icon-clothes:before { + content: "\e8d1"; +} + .icon-caizhi:before { content: "\e647"; } diff --git a/src/assets/iconfont2/iconfont.js b/src/assets/iconfont2/iconfont.js new file mode 100644 index 00000000..e883181a --- /dev/null +++ b/src/assets/iconfont2/iconfont.js @@ -0,0 +1 @@ +window._iconfont_svg_string_4292253='',(c=>{var a=(l=(l=document.getElementsByTagName("script"))[l.length-1]).getAttribute("data-injectcss"),l=l.getAttribute("data-disable-injectsvg");if(!l){var i,t,o,h,e,n=function(a,l){l.parentNode.insertBefore(a,l)};if(a&&!c.__iconfont__svg__cssinject__){c.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(a){console&&console.log(a)}}i=function(){var a,l=document.createElement("div");l.innerHTML=c._iconfont_svg_string_4292253,(l=l.getElementsByTagName("svg")[0])&&(l.setAttribute("aria-hidden","true"),l.style.position="absolute",l.style.width=0,l.style.height=0,l.style.overflow="hidden",l=l,(a=document.body).firstChild?n(l,a.firstChild):a.appendChild(l))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(i,0):(t=function(){document.removeEventListener("DOMContentLoaded",t,!1),i()},document.addEventListener("DOMContentLoaded",t,!1)):document.attachEvent&&(o=i,h=c.document,e=!1,s(),h.onreadystatechange=function(){"complete"==h.readyState&&(h.onreadystatechange=null,m())})}function m(){e||(e=!0,o())}function s(){try{h.documentElement.doScroll("left")}catch(a){return void setTimeout(s,50)}m()}})(window); \ No newline at end of file diff --git a/src/assets/iconfont2/iconfont.json b/src/assets/iconfont2/iconfont.json index 578a73da..75657853 100644 --- a/src/assets/iconfont2/iconfont.json +++ b/src/assets/iconfont2/iconfont.json @@ -1,170 +1,247 @@ { - "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": "22138606", + "name": "裁剪", + "font_class": "caijian", + "unicode": "e650", + "unicode_decimal": 58960 }, { - "icon_id": "125198319", - "name": "撤销 返回 撤回 上一步", - "font_class": "fanchehui", - "unicode": "e626", - "unicode_decimal": 58918 + "icon_id": "8875396", + "name": "角度", + "font_class": "angle", + "unicode": "e60a", + "unicode_decimal": 58890 }, { - "icon_id": "125198320", - "name": "撤销 返回 撤回 上一步", - "font_class": "chehui", - "unicode": "e609", - "unicode_decimal": 58889 + "icon_id": "15551512", + "name": "水平翻转", + "font_class": "flip-horizontal", + "unicode": "e69e", + "unicode_decimal": 59038 }, { - "icon_id": "125524062", - "name": "语言", - "font_class": "yuyan", - "unicode": "e85f", - "unicode_decimal": 59487 + "icon_id": "46016160", + "name": "垂直翻转", + "font_class": "flip-vertical", + "unicode": "ec60", + "unicode_decimal": 60512 }, { - "icon_id": "126177191", - "name": "标签", - "font_class": "biaoqian", - "unicode": "e603", - "unicode_decimal": 58883 + "icon_id": "20183053", + "name": "clothes", + "font_class": "clothes", + "unicode": "e8d1", + "unicode_decimal": 59601 }, { - "icon_id": "126459101", - "name": "并集", - "font_class": "bingji", - "unicode": "e620", - "unicode_decimal": 58912 + "icon_id": "15739173", + "name": "材质", + "font_class": "caizhi", + "unicode": "e647", + "unicode_decimal": 58951 }, { - "icon_id": "126459102", - "name": "并集", - "font_class": "bingji1", - "unicode": "e668", - "unicode_decimal": 58984 + "icon_id": "35023469", + "name": "IC-液化", + "font_class": "IC-yehua", + "unicode": "e61b", + "unicode_decimal": 58907 }, { - "icon_id": "126901286", - "name": "点位", - "font_class": "dianwei", - "unicode": "e685", - "unicode_decimal": 59013 + "icon_id": "12096844", + "name": "上一层", + "font_class": "shangyiceng", + "unicode": "e751", + "unicode_decimal": 59217 }, { - "icon_id": "130743908", - "name": "编辑", - "font_class": "bianji", - "unicode": "e600", - "unicode_decimal": 58880 + "icon_id": "16531912", + "name": "上一层", + "font_class": "shangyiceng1", + "unicode": "e604", + "unicode_decimal": 58884 }, { - "icon_id": "130743909", - "name": "圆形", - "font_class": "circle", - "unicode": "e64f", - "unicode_decimal": 58959 + "icon_id": "24253227", + "name": "下一层", + "font_class": "xiayiceng", + "unicode": "e68a", + "unicode_decimal": 59018 }, { - "icon_id": "130743910", - "name": "三角形", - "font_class": "sanjiaoxing", - "unicode": "e615", - "unicode_decimal": 58901 + "icon_id": "24253230", + "name": "上一层", + "font_class": "shangyiceng2", + "unicode": "e68b", + "unicode_decimal": 59019 }, { - "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 } ] } diff --git a/src/assets/iconfont2/iconfont.ttf b/src/assets/iconfont2/iconfont.ttf index 905838aa..91080201 100644 Binary files a/src/assets/iconfont2/iconfont.ttf and b/src/assets/iconfont2/iconfont.ttf differ diff --git a/src/assets/iconfont2/iconfont.woff b/src/assets/iconfont2/iconfont.woff index a1c35fd0..54a3be20 100644 Binary files a/src/assets/iconfont2/iconfont.woff and b/src/assets/iconfont2/iconfont.woff differ diff --git a/src/assets/iconfont2/iconfont.woff2 b/src/assets/iconfont2/iconfont.woff2 index 3fc507c2..b9d64f8d 100644 Binary files a/src/assets/iconfont2/iconfont.woff2 and b/src/assets/iconfont2/iconfont.woff2 differ diff --git a/src/assets/icons/CCharge.svg b/src/assets/icons/CCharge.svg new file mode 100644 index 00000000..82893442 --- /dev/null +++ b/src/assets/icons/CCharge.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/icons/CCheck.svg b/src/assets/icons/CCheck.svg new file mode 100644 index 00000000..1c25b56c --- /dev/null +++ b/src/assets/icons/CCheck.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/CClothes.svg b/src/assets/icons/CClothes.svg new file mode 100644 index 00000000..bcbd739a --- /dev/null +++ b/src/assets/icons/CClothes.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/CCopy.svg b/src/assets/icons/CCopy.svg new file mode 100644 index 00000000..0c3cad55 --- /dev/null +++ b/src/assets/icons/CCopy.svg @@ -0,0 +1,2 @@ + + diff --git a/src/assets/icons/CDownload.svg b/src/assets/icons/CDownload.svg new file mode 100644 index 00000000..5e2793ba --- /dev/null +++ b/src/assets/icons/CDownload.svg @@ -0,0 +1,2 @@ + + diff --git a/src/assets/icons/CHelpFlip.svg b/src/assets/icons/CHelpFlip.svg new file mode 100644 index 00000000..0da6d330 --- /dev/null +++ b/src/assets/icons/CHelpFlip.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/icons/CLibrary.svg b/src/assets/icons/CLibrary.svg new file mode 100644 index 00000000..ce0f94c5 --- /dev/null +++ b/src/assets/icons/CLibrary.svg @@ -0,0 +1,2 @@ + + diff --git a/src/assets/icons/CPause.svg b/src/assets/icons/CPause.svg new file mode 100644 index 00000000..4c60d244 --- /dev/null +++ b/src/assets/icons/CPause.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/assets/icons/CPlay.svg b/src/assets/icons/CPlay.svg new file mode 100644 index 00000000..a200e02d --- /dev/null +++ b/src/assets/icons/CPlay.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/CSearch.svg b/src/assets/icons/CSearch.svg new file mode 100644 index 00000000..96a25348 --- /dev/null +++ b/src/assets/icons/CSearch.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/DetailCompare.svg b/src/assets/icons/DetailCompare.svg new file mode 100644 index 00000000..aeceaf6b --- /dev/null +++ b/src/assets/icons/DetailCompare.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/icons/Folder.svg b/src/assets/icons/Folder.svg new file mode 100644 index 00000000..abfd060d --- /dev/null +++ b/src/assets/icons/Folder.svg @@ -0,0 +1,22 @@ + + + + + + + + diff --git a/src/assets/icons/promptEditProductNo.svg b/src/assets/icons/promptEditProductNo.svg new file mode 100644 index 00000000..36951dfb --- /dev/null +++ b/src/assets/icons/promptEditProductNo.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/promptEditProductYes.svg b/src/assets/icons/promptEditProductYes.svg new file mode 100644 index 00000000..daf0070b --- /dev/null +++ b/src/assets/icons/promptEditProductYes.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/images/editProduct/PromptEditProduct_edited1.png b/src/assets/images/editProduct/PromptEditProduct_edited1.png new file mode 100644 index 00000000..e86b412b Binary files /dev/null and b/src/assets/images/editProduct/PromptEditProduct_edited1.png differ diff --git a/src/assets/images/editProduct/PromptEditProduct_edited2.png b/src/assets/images/editProduct/PromptEditProduct_edited2.png new file mode 100644 index 00000000..2f0000a5 Binary files /dev/null and b/src/assets/images/editProduct/PromptEditProduct_edited2.png differ diff --git a/src/assets/images/editProduct/PromptEditProduct_edited3.png b/src/assets/images/editProduct/PromptEditProduct_edited3.png new file mode 100644 index 00000000..999f89c3 Binary files /dev/null and b/src/assets/images/editProduct/PromptEditProduct_edited3.png differ diff --git a/src/assets/images/editProduct/PromptEditProduct_list1.png b/src/assets/images/editProduct/PromptEditProduct_list1.png new file mode 100644 index 00000000..b938ca1a Binary files /dev/null and b/src/assets/images/editProduct/PromptEditProduct_list1.png differ diff --git a/src/assets/images/editProduct/PromptEditProduct_list10.png b/src/assets/images/editProduct/PromptEditProduct_list10.png new file mode 100644 index 00000000..54393214 Binary files /dev/null and b/src/assets/images/editProduct/PromptEditProduct_list10.png differ diff --git a/src/assets/images/editProduct/PromptEditProduct_list11.png b/src/assets/images/editProduct/PromptEditProduct_list11.png new file mode 100644 index 00000000..61d658df Binary files /dev/null and b/src/assets/images/editProduct/PromptEditProduct_list11.png differ diff --git a/src/assets/images/editProduct/PromptEditProduct_list2.png b/src/assets/images/editProduct/PromptEditProduct_list2.png new file mode 100644 index 00000000..b305848e Binary files /dev/null and b/src/assets/images/editProduct/PromptEditProduct_list2.png differ diff --git a/src/assets/images/editProduct/PromptEditProduct_list3.png b/src/assets/images/editProduct/PromptEditProduct_list3.png new file mode 100644 index 00000000..62577bf1 Binary files /dev/null and b/src/assets/images/editProduct/PromptEditProduct_list3.png differ diff --git a/src/assets/images/editProduct/PromptEditProduct_list4.png b/src/assets/images/editProduct/PromptEditProduct_list4.png new file mode 100644 index 00000000..dadf1858 Binary files /dev/null and b/src/assets/images/editProduct/PromptEditProduct_list4.png differ diff --git a/src/assets/images/editProduct/PromptEditProduct_list5.png b/src/assets/images/editProduct/PromptEditProduct_list5.png new file mode 100644 index 00000000..913c9d49 Binary files /dev/null and b/src/assets/images/editProduct/PromptEditProduct_list5.png differ diff --git a/src/assets/images/editProduct/PromptEditProduct_list6.png b/src/assets/images/editProduct/PromptEditProduct_list6.png new file mode 100644 index 00000000..35e03c4f Binary files /dev/null and b/src/assets/images/editProduct/PromptEditProduct_list6.png differ diff --git a/src/assets/images/editProduct/PromptEditProduct_list7.png b/src/assets/images/editProduct/PromptEditProduct_list7.png new file mode 100644 index 00000000..43f62618 Binary files /dev/null and b/src/assets/images/editProduct/PromptEditProduct_list7.png differ diff --git a/src/assets/images/editProduct/PromptEditProduct_list8.png b/src/assets/images/editProduct/PromptEditProduct_list8.png new file mode 100644 index 00000000..ede4506f Binary files /dev/null and b/src/assets/images/editProduct/PromptEditProduct_list8.png differ diff --git a/src/assets/images/editProduct/PromptEditProduct_list9.png b/src/assets/images/editProduct/PromptEditProduct_list9.png new file mode 100644 index 00000000..0568333e Binary files /dev/null and b/src/assets/images/editProduct/PromptEditProduct_list9.png differ diff --git a/src/assets/images/editProduct/PromptEditProduct_listOriginal.png b/src/assets/images/editProduct/PromptEditProduct_listOriginal.png new file mode 100644 index 00000000..e86b412b Binary files /dev/null and b/src/assets/images/editProduct/PromptEditProduct_listOriginal.png differ diff --git a/src/assets/images/homePage/designTutorial_CN.png b/src/assets/images/homePage/designTutorial_CN.png new file mode 100644 index 00000000..7d0c1bc3 Binary files /dev/null and b/src/assets/images/homePage/designTutorial_CN.png differ diff --git a/src/assets/images/homePage/designTutorial_EN.png b/src/assets/images/homePage/designTutorial_EN.png new file mode 100644 index 00000000..10191929 Binary files /dev/null and b/src/assets/images/homePage/designTutorial_EN.png differ diff --git a/src/assets/images/icon/library.png b/src/assets/images/icon/library.png new file mode 100644 index 00000000..60b8e7bf Binary files /dev/null and b/src/assets/images/icon/library.png differ diff --git a/src/assets/images/icon/selected.png b/src/assets/images/icon/selected.png new file mode 100644 index 00000000..149bc06a Binary files /dev/null and b/src/assets/images/icon/selected.png differ diff --git a/src/assets/images/icon/upload_black.png b/src/assets/images/icon/upload_black.png new file mode 100644 index 00000000..635249c7 Binary files /dev/null and b/src/assets/images/icon/upload_black.png differ diff --git a/src/assets/images/icon/upload_gray.png b/src/assets/images/icon/upload_gray.png new file mode 100644 index 00000000..4e109e29 Binary files /dev/null and b/src/assets/images/icon/upload_gray.png differ diff --git a/src/assets/images/product/add.png b/src/assets/images/product/add.png new file mode 100644 index 00000000..7fece2f3 Binary files /dev/null and b/src/assets/images/product/add.png differ diff --git a/src/assets/images/product/first_frame.png b/src/assets/images/product/first_frame.png new file mode 100644 index 00000000..edceb6ff Binary files /dev/null and b/src/assets/images/product/first_frame.png differ diff --git a/src/assets/images/product/geneated_dress.png b/src/assets/images/product/geneated_dress.png new file mode 100644 index 00000000..cbbdfa01 Binary files /dev/null and b/src/assets/images/product/geneated_dress.png differ diff --git a/src/assets/images/product/generated_model.png b/src/assets/images/product/generated_model.png new file mode 100644 index 00000000..15c3d176 Binary files /dev/null and b/src/assets/images/product/generated_model.png differ diff --git a/src/assets/images/product/generated_sketch.png b/src/assets/images/product/generated_sketch.png new file mode 100644 index 00000000..37c8d36d Binary files /dev/null and b/src/assets/images/product/generated_sketch.png differ diff --git a/src/assets/images/product/last_frame.png b/src/assets/images/product/last_frame.png new file mode 100644 index 00000000..1d4d7791 Binary files /dev/null and b/src/assets/images/product/last_frame.png differ diff --git a/src/assets/images/product/male_single_garment_model_result.png b/src/assets/images/product/male_single_garment_model_result.png new file mode 100644 index 00000000..3917056d Binary files /dev/null and b/src/assets/images/product/male_single_garment_model_result.png differ diff --git a/src/assets/images/product/male_single_garment_model_sketch.png b/src/assets/images/product/male_single_garment_model_sketch.png new file mode 100644 index 00000000..59dcc70a Binary files /dev/null and b/src/assets/images/product/male_single_garment_model_sketch.png differ diff --git a/src/assets/images/product/male_single_garment_result.png b/src/assets/images/product/male_single_garment_result.png new file mode 100644 index 00000000..59d16cff Binary files /dev/null and b/src/assets/images/product/male_single_garment_result.png differ diff --git a/src/assets/images/product/male_single_garment_sketch.png b/src/assets/images/product/male_single_garment_sketch.png new file mode 100644 index 00000000..79c80e7f Binary files /dev/null and b/src/assets/images/product/male_single_garment_sketch.png differ diff --git a/src/assets/images/product/original_dress.png b/src/assets/images/product/original_dress.png new file mode 100644 index 00000000..2ad7f2e5 Binary files /dev/null and b/src/assets/images/product/original_dress.png differ diff --git a/src/assets/images/product/original_model.png b/src/assets/images/product/original_model.png new file mode 100644 index 00000000..c61590d9 Binary files /dev/null and b/src/assets/images/product/original_model.png differ diff --git a/src/assets/images/product/single_female_child_model_result.png b/src/assets/images/product/single_female_child_model_result.png new file mode 100644 index 00000000..2a34380f Binary files /dev/null and b/src/assets/images/product/single_female_child_model_result.png differ diff --git a/src/assets/images/product/single_male_child_model_result.png b/src/assets/images/product/single_male_child_model_result.png new file mode 100644 index 00000000..06d45068 Binary files /dev/null and b/src/assets/images/product/single_male_child_model_result.png differ diff --git a/src/assets/images/product/single_male_child_model_sketch.png b/src/assets/images/product/single_male_child_model_sketch.png new file mode 100644 index 00000000..7a8800e3 Binary files /dev/null and b/src/assets/images/product/single_male_child_model_sketch.png differ diff --git a/src/assets/images/socialMediaLogo/biliBliIcon.png b/src/assets/images/socialMediaLogo/biliBliIcon.png new file mode 100644 index 00000000..21a861d7 Binary files /dev/null and b/src/assets/images/socialMediaLogo/biliBliIcon.png differ diff --git a/src/assets/images/socialMediaLogo/instagramIcon.png b/src/assets/images/socialMediaLogo/instagramIcon.png new file mode 100644 index 00000000..6fd366b6 Binary files /dev/null and b/src/assets/images/socialMediaLogo/instagramIcon.png differ diff --git a/src/assets/images/socialMediaLogo/tikTokIcon.png b/src/assets/images/socialMediaLogo/tikTokIcon.png new file mode 100644 index 00000000..1fa7db89 Binary files /dev/null and b/src/assets/images/socialMediaLogo/tikTokIcon.png differ diff --git a/src/assets/images/socialMediaLogo/xiaoHongShuIcon.png b/src/assets/images/socialMediaLogo/xiaoHongShuIcon.png new file mode 100644 index 00000000..44fa3fa1 Binary files /dev/null and b/src/assets/images/socialMediaLogo/xiaoHongShuIcon.png differ diff --git a/src/assets/images/socialMediaLogo/youTubeIcon.png b/src/assets/images/socialMediaLogo/youTubeIcon.png new file mode 100644 index 00000000..3e6b31e8 Binary files /dev/null and b/src/assets/images/socialMediaLogo/youTubeIcon.png differ diff --git a/src/assets/images/socialMediaLogo/zhiHuIcon.png b/src/assets/images/socialMediaLogo/zhiHuIcon.png new file mode 100644 index 00000000..1cd479e3 Binary files /dev/null and b/src/assets/images/socialMediaLogo/zhiHuIcon.png differ diff --git a/src/assets/json/events.json b/src/assets/json/events.json index fdc4a527..f7447995 100644 --- a/src/assets/json/events.json +++ b/src/assets/json/events.json @@ -8,14 +8,6 @@ "id": 2, "title":"AiDA X SFT AI Fashion Award 2024", "imgUrl": "/image/events/Fashion-Award-2024.png" - },{ - "id": 3, - "title":"✨New Year 2025!🎉Let's kick off the year with a burst of inspiration and design!", - "imgUrl": "/image/events/AiDA2025-En.jpg" - },{ - "id": 4, - "title":"Welcome back !Subscribe with the discount code to enjoy 50% OFF!", - "imgUrl": "/image/events/Welcome-back-En.jpg" } ], "eventsItem":[ @@ -96,106 +88,6 @@ ] } ] - },{ - "id":3, - "title":"✨New Year 2025!🎉Let's kick off the year with a burst of inspiration and design!", - "imgUrl": "/image/events/AiDA2025-En.jpg", - "textList":[ - { - "paragraph":[ - { - "text":"Share your work and get 1 month of free access to AiDA!" - } - ] - },{ - "paragraph":[ - { - "text":" Just do the following:" - } - ] - },{ - "paragraph":[ - { - "text":" ✅Share your designs on AiDA's Gallery " - },{ - "text":" ✅Add the tag #NewYear_2025 in the work description" - },{ - "text":" ✅At least 20 likes " - } - ] - },{ - "paragraph":[ - { - "text":"📅 Duration: January 1, 2025 – January 31, 2025" - } - ] - },{ - "paragraph":[ - { - "text":"Join in the fun and embark on a new year's journey of design. Mix your creativity with tech to make amazing, unique creations! Get your friends to help you seize this opportunity! Invite them to give your design some love with their likes~💗" - } - ] - },{ - "paragraph":[ - { - "text":"👍 AiDA is waiting for you to unlock a new world of design!" - } - ] - } - ] - },{ - "id":4, - "title":"Welcome back !Subscribe with the discount code to enjoy 50% OFF!", - "imgUrl": "/image/events/Welcome-back-En.jpg", - "textList":[ - { - "paragraph":[ - { - "text":"💠 In February, AiDA underwent a legendary transformation" - },{ - "text":"💠 A silky-smooth interface and a turbocharged upgrade to all functions" - },{ - "text":"😆 Long-time users are saying: “Wait… is this still the AiDA I knew?!" - } - ] - },{ - "paragraph":[ - { - "text":"Demo video👉 https://sg834.apps.aliyunpds.com/disk/s/R6SsxBaju9h" - } - ] - },{ - "paragraph":[ - { - "text":"⚡️ To welcome back our trial users, we’ve prepared an exclusive design power-up:" - },{ - "text":"✔️ Use the promo code「RIINRMKK」 and enjoy 50% off your subscription" - },{ - "text":"✔️ Boost your efficiency by 60%—save hours on every project" - },{ - "text":"✔️ sNo design background? No problem! Get stunning drafts in just 5 minutes" - } - ] - },{ - "paragraph":[ - { - "text":"⏳ The countdown is on:" - },{ - "text":"✨Ignite your creativity like a volcanic eruption" - },{ - "text":"✨Let your inspiration flow like a cosmic waterfall" - } - ] - },{ - "paragraph":[ - { - "text":"Promotional Code: RIINRMKK" - },{ - "text":"Duration: June 10 to June 30, 2025 – After that, subscriptions return to full price. Don’t miss it!" - } - ] - } - ] } ] } \ No newline at end of file diff --git a/src/assets/json/events_cn.json b/src/assets/json/events_cn.json index 8eca3240..ce253a69 100644 --- a/src/assets/json/events_cn.json +++ b/src/assets/json/events_cn.json @@ -8,15 +8,7 @@ "id": 2, "title":"AiDA X SFT AI时尚设计比赛2024", "imgUrl": "/image/events/Fashion-Award-2024.png" - },{ - "id": 3, - "title":"🎉搭上2025的列车!打开新设计的大门!", - "imgUrl": "/image/events/AiDA2025-Cn.jpg" - },{ - "id": 4, - "title":"设计时速狂飙!AiDA 618半价让灵感永不限流!", - "imgUrl": "/image/events/Welcome-back-Cn.jpg" - } + } ], "eventsItem":[ { @@ -96,112 +88,6 @@ ] } ] - },{ - "id":3, - "title":"🎉搭上2025的列车!打开新设计的大门!", - "imgUrl": "/image/events/AiDA2025-Cn.jpg", - "textList":[ - { - "paragraph":[ - { - "text":"快来发布作品获得1个月免费使用AiDA的福利!" - } - ] - },{ - "paragraph":[ - { - "text":" 只需要:" - } - ] - },{ - "paragraph":[ - { - "text":" ✅在AiDA将设计作品分享至广场/Gallery," - },{ - "text":" ✅点赞至少20" - },{ - "text":" ✅在作品描述加上tag #NewYear_2025" - } - ] - },{ - "paragraph":[ - { - "text":"📅 活动时间:2025.1.1—2025.1.31" - } - ] - },{ - "paragraph":[ - { - "text":"快来参与,让我们共同开启新年的设计之旅,让创意与科技完美融合,创造出属于你的独一无二的作品!机会难得,叫上你的朋友们助你一臂之力,为你点上大拇指哦!" - } - ] - },{ - "paragraph":[ - { - "text":"👍 点赞即启程,AiDA等你来解锁设计新世界!" - } - ] - } - ] - },{ - "id":4, - "title":"设计时速狂飙!AiDA 618半价让灵感永不限流!", - "imgUrl": "/image/events/Welcome-back-En.jpg", - "textList":[ - { - "paragraph":[ - { - "text":"618的钟声敲响,AiDA的AI设计宇宙正式进入「超维折扣纪元」" - } - ] - },{ - "paragraph":[ - { - "text":"💠 就在今年2月,AiDA完成史诗级进化" - },{ - "text":"💠 界面如丝绸般顺滑,功能矩阵全面升级。" - },{ - "text":"😆 旧版用户惊呼:这还是我认识的AiDA吗⁉️" - } - ] - },{ - "paragraph":[ - { - "text":"演示视频👉 https://sg834.apps.aliyunpds.com/disk/s/R6SsxBaju9h" - } - ] - },{ - "paragraph":[ - { - "text":"⚡️ 618特供「专属暴击福利」💥" - },{ - "text":"✔️ 输入口令“RIINRMKK”订阅,直接享受半价!" - },{ - "text":"✔️ 效率提升60%,设计实践节省一大半!" - },{ - "text":"✔️ 零基础也能5分钟出稿,轻松搞定设计需求" - } - ] - },{ - "paragraph":[ - { - "text":"⏳ 倒计时警报:" - },{ - "text":"👉 让设计如火山喷发般炽热" - },{ - "text":"👉 让灵感似银河倾泻般璀璨" - } - ] - },{ - "paragraph":[ - { - "text":"优惠码:RIINRMKK" - },{ - "text":"活动日期:2025.6.10-6.30(后续订阅费用将恢复至原价)" - } - ] - } - ] } ] } \ No newline at end of file diff --git a/src/assets/style/style.css b/src/assets/style/style.css index feaf5ae3..d917340c 100644 --- a/src/assets/style/style.css +++ b/src/assets/style/style.css @@ -62,6 +62,9 @@ li { height: 100%; margin: 0 auto; } +.ant-dropdown-menu { + border-radius: 1rem; +} .button_second { width: 14rem; text-align: center; @@ -165,6 +168,7 @@ li { } .ant-modal-mask { background-color: #666666; + opacity: 0.5; } .select_block { height: 4rem; @@ -237,7 +241,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; @@ -1247,7 +1251,9 @@ tr > .ant-picker-cell-in-view.ant-picker-cell-range-hover-start:last-child::afte border-color: #000 !important; } .ant-spin-dot-item { - background-color: #000000; + background-color: #000000 !important; + width: 9px !important; + height: 9px !important; } .ant-spin { color: #000; @@ -1373,7 +1379,7 @@ tr > .ant-picker-cell-in-view.ant-picker-cell-range-hover-start:last-child::afte } .admin_page .admin_state_item .active { cursor: no-drop; - background-color: #f5f5f5; + background-color: #F9FAFA; } .admin_page .admin_search_item { height: 4rem; @@ -1707,7 +1713,7 @@ textarea:focus { display: inline-block; width: calc(25% - 2rem); aspect-ratio: 1 / 1; - border: 1px solid #f5f5f5; + border: 1px solid #F9FAFA; vertical-align: top; position: relative; cursor: pointer; @@ -1989,7 +1995,7 @@ textarea:focus { display: flex; float: left; align-items: center; - padding: 1.5rem 2rem; + padding: 1rem 2rem; background-color: #fff; flex: 1; height: auto; @@ -2314,6 +2320,8 @@ textarea:focus { top: 0rem; flex: 1; border: 1px solid #dcdfe6; + width: calc(var(--width) + 6rem); + padding: 1rem; } .generage_btn_box { position: relative; diff --git a/src/assets/style/style.less b/src/assets/style/style.less index d87b4d12..938f0a7b 100644 --- a/src/assets/style/style.less +++ b/src/assets/style/style.less @@ -63,6 +63,9 @@ input:focus{ height: 100%; margin: 0 auto; } +.ant-dropdown-menu{ + border-radius: 1rem; +} .button_second{ width: 14rem; text-align: center; @@ -170,6 +173,7 @@ input:focus{ } .ant-modal-mask{ background-color: #666666; + opacity: .5; } .select_block{ height: 4rem; @@ -241,7 +245,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; @@ -1375,7 +1379,9 @@ tr > .ant-picker-cell-in-view.ant-picker-cell-range-hover-start:last-child::afte } //loding样式 .ant-spin-dot-item{ - background-color: #000000; + background-color: #000000 !important; + width: 9px !important; + height: 9px !important; } .ant-spin{ color: #000; @@ -1507,7 +1513,7 @@ tr > .ant-picker-cell-in-view.ant-picker-cell-range-hover-start:last-child::afte } .active{ cursor: no-drop; - background-color: #f5f5f5; + background-color: #F9FAFA; } } .admin_search_item{ @@ -1862,7 +1868,7 @@ textarea:focus{ // height: calc(10rem); width: calc(25% - 2rem); aspect-ratio: 1 / 1; - border: 1px solid #f5f5f5; + border: 1px solid #F9FAFA; vertical-align: top; position: relative; cursor: pointer; @@ -2057,7 +2063,7 @@ textarea:focus{ display: flex; float: left; align-items: center; - padding: 1.5rem 2rem; + padding: 1rem 2rem; // padding-right: 0; background-color: #fff; flex: 1; @@ -2200,6 +2206,8 @@ textarea:focus{ top: 0rem; flex: 1; border: 1px solid #dcdfe6; + width: calc(var(--width) + 6rem); + padding: 1rem; } // span{ diff --git a/src/component/Account/account.vue b/src/component/Account/account.vue index 57f7a42e..6a9280e5 100644 --- a/src/component/Account/account.vue +++ b/src/component/Account/account.vue @@ -50,10 +50,10 @@
{{ userDetail.email }}
-
+
diff --git a/src/component/Account/frontPage.vue b/src/component/Account/frontPage.vue index c735153a..a6732c3e 100644 --- a/src/component/Account/frontPage.vue +++ b/src/component/Account/frontPage.vue @@ -6,7 +6,7 @@ @@ -104,6 +104,12 @@ export default defineComponent({ let key = accountfrontPage.frontPageList[0].key accountfrontPage.activeKey = key const data = route.query + if(!!data.subscribe){ + accountfrontPage.activeKey = 'cancelRenewal' + nextTick(()=>{ + domRefs.cancelRenewal[0].subscribe() + }) + } if(data?.state == 'weiXin'){ accountfrontPage.activeKey = 'bind' wechatLogin(data) diff --git a/src/component/Account/frontPage/bindPage.vue b/src/component/Account/frontPage/bindPage.vue index 0557f7e9..825781f4 100644 --- a/src/component/Account/frontPage/bindPage.vue +++ b/src/component/Account/frontPage/bindPage.vue @@ -27,10 +27,10 @@
--> -
- - - +
+ +
+
@@ -111,39 +111,58 @@ 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') } - const toGmailLogin = ()=>{ - message.info(t('account.canNotUtilize')) - } onMounted(async ()=>{ - return - let GOOGLE_CLIENT_ID = '29310152396-nnsd3h533fld665oguu8ovrt1nukmt46.apps.googleusercontent.com' + let GOOGLE_CLIENT_ID + if(import.meta.env.VITE_USER_NODE_ENV == 'development'){ + GOOGLE_CLIENT_ID = '157095842121-kdd1fdf8m8nudvj9sprstb2k2prnf9e4.apps.googleusercontent.com' + }else{ + GOOGLE_CLIENT_ID = '29310152396-nnsd3h533fld665oguu8ovrt1nukmt46.apps.googleusercontent.com' + } var existingScript = document.querySelector(`script[src="${data.scriptSrc}"]`); if(!window.isAddGmail){ if(!existingScript){ @@ -206,7 +225,6 @@ export default defineComponent({ ungroupGoogleModel, ungroupWeiXinModel, modifyEmail, - toGmailLogin, } }, data(){ @@ -271,14 +289,21 @@ export default defineComponent({ } >.gmail_btn{ position: relative; + border-radius: 4rem; + overflow: hidden; + > .gallery_btn{ + position: relative; + z-index: 2; + + } #g_id_bind{ position: absolute; left: 0; top: 0; width: 100%; height: 100%; - opacity: 0; - z-index: 2; + // opacity: 0; + z-index: 1; :deep(.nsm7Bb-HzV7m-LgbsSe.Bz112c-LgbsSe){ width: 100%; } diff --git a/src/component/Account/frontPage/mylnformation.vue b/src/component/Account/frontPage/mylnformation.vue index e5df3e55..72da23b4 100644 --- a/src/component/Account/frontPage/mylnformation.vue +++ b/src/component/Account/frontPage/mylnformation.vue @@ -28,7 +28,7 @@ optionFilterProp="label" :options="countryList" :field-names="{ label: locale == 'CHINESE_SIMPLIFIED'?'labelCn':'label' }" - placeholder="Please select" + :placeholder="`${$t('account.plaseSelect')} ${$t('account.Country')}`" allowClear show-search > @@ -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 }) diff --git a/src/component/Account/message/system.vue b/src/component/Account/message/system.vue index 0ec97451..8795031f 100644 --- a/src/component/Account/message/system.vue +++ b/src/component/Account/message/system.vue @@ -133,8 +133,14 @@ export default defineComponent({ } .modal_title_text_intro{ margin-left: 4rem; + } } } + .modal_title_text_intro{ + word-break: break-word; + white-space: pre-wrap; + font-family: Arial, sans-serif; + } } diff --git a/src/component/Administrator/SE/allUser/index.vue b/src/component/Administrator/SE/allUser/index.vue index 28309f70..ebfe2ca1 100644 --- a/src/component/Administrator/SE/allUser/index.vue +++ b/src/component/Administrator/SE/allUser/index.vue @@ -22,7 +22,7 @@ +
+ State: + +
Close
@@ -96,14 +101,29 @@ export default defineComponent({ id: "", commission: "", }); + let currentState = ref('') + let state = ref([ + { + label:'Active', + value:'Active', + }, + { + label:'Delete', + value:'Delete', + }, + { + label:'Inactive', + value:'Inactive', + }, + ]) let init = (data) => { let funStr = 'Edit' - console.log(data) operations.operationsModal = true; operations.title = funStr; if (funStr == "Edit") { operationsData.id = data.id; operationsData.commission = data.commissionPercent; + currentState.value = data.status; } }; @@ -111,11 +131,13 @@ export default defineComponent({ return { id: operationsData.id, commission: operationsData.commission, + operationType: currentState.value, }; }; let cancelDsign = () => { operationsData.id = ""; operationsData.commission = ""; + currentState.value = ""; operations.operationsModal = false; }; let setOk = () => { @@ -125,7 +147,7 @@ export default defineComponent({ !data.commission ) return message.warning("Please check the input box marked with *"); - Https.axiosGet(Https.httpUrls.updateCommission, {params:data}).then( + Https.axiosGet(Https.httpUrls.editAffiliate, {params:data}).then( (rv) => { if (rv) { cancelDsign(); @@ -139,6 +161,8 @@ export default defineComponent({ ...toRefs(operationsData), cancelDsign, init, + state, + currentState, setOk, }; }, diff --git a/src/component/Administrator/allUser.vue b/src/component/Administrator/allUser.vue index eb4535a1..a1ab6876 100644 --- a/src/component/Administrator/allUser.vue +++ b/src/component/Administrator/allUser.vue @@ -26,7 +26,7 @@
-->
- Country: + Country or Region:
- Country: + Country or Region: -
- -
-
- - - - - -
-
- -
-
- Cooperator: - -
-
- percentOff(%): * - -
-
- Commission Rate: * - -
-
- - End Time: * - - - -
-
- MaxRedemptions: - -
-
- PaidCommission: - -
-
- Remark: - -
-
-
-
Close
-
OK
-
-
-
- -
- - - - + + + \ No newline at end of file diff --git a/src/component/Administrator/organization/organization.vue b/src/component/Administrator/organization/organization.vue index f3fb8d79..0488bed0 100644 --- a/src/component/Administrator/organization/organization.vue +++ b/src/component/Administrator/organization/organization.vue @@ -1,228 +1,305 @@ \ No newline at end of file diff --git a/src/component/Administrator/recentActiveUser.vue b/src/component/Administrator/recentActiveUser.vue index 421ef4af..daa044e9 100644 --- a/src/component/Administrator/recentActiveUser.vue +++ b/src/component/Administrator/recentActiveUser.vue @@ -150,11 +150,11 @@ export default defineComponent({ }, }, { - title: "Country", + title: "Country or Region", align: "center", dataIndex: "country", key: "country", - width:100, + width:200, }, { title: "Create Date", @@ -242,7 +242,11 @@ export default defineComponent({ filterData.orderBy = 'credits' } } - filterData.order = sorter.order == "descend" ? "Descending" : "Ascending"; + if(sorter.order){ + filterData.order = sorter.order == "descend" ? "Descending" : "Ascending"; + }else{ + filterData.order = '' + } gettrialList(); } diff --git a/src/component/Administrator/recentNewUser.vue b/src/component/Administrator/recentNewUser.vue index da8a628a..26dd113c 100644 --- a/src/component/Administrator/recentNewUser.vue +++ b/src/component/Administrator/recentNewUser.vue @@ -177,11 +177,11 @@ export default defineComponent({ }, }, { - title: "Country", + title: "Country or Region", align: "center", dataIndex: "country", key: "country", - width:100, + width:200, }, { title: "Create Date", @@ -268,7 +268,11 @@ export default defineComponent({ filterData.orderBy = 'credits' } } - filterData.order = sorter.order == "descend" ? "Descending" : "Ascending"; + if(sorter.order){ + filterData.order = sorter.order == "descend" ? "Descending" : "Ascending"; + }else{ + filterData.order = '' + } gettrialList(); } diff --git a/src/component/Administrator/trialAllUser.vue b/src/component/Administrator/trialAllUser.vue index 606887b1..3d5bd635 100644 --- a/src/component/Administrator/trialAllUser.vue +++ b/src/component/Administrator/trialAllUser.vue @@ -23,7 +23,7 @@
- Country: + Country or Region: 0 ) { // 移除新添加的填充对象 - if (canvasObj._objects?.[0] === this.newFill) { + // if (canvasObj._objects?.[0] === this.newFill) { + if (/^fill-/.test(canvasObj._objects?.[0]?.id)) { canvasObj._objects.shift(); canvasObj.addWithUpdate(); canvasObj.setCoords(); @@ -284,6 +296,14 @@ export class FillGroupLayerBackgroundCommand extends Command { this.canvas.renderAll(); this.group = null; } + if(this.oldFill){ + this.layer.fill = this.oldFill; + this.layer.fillColor = this.oldFillColor; + return this.execute(true); + }else{ + this.layer.fill = null; + this.layer.fillColor = null; + } this.canvas.discardActiveObject(); // 取消当前活动对象 // 重新排序 diff --git a/src/component/Canvas/CanvasEditor/commands/LassoCutoutCommand.bak.js b/src/component/Canvas/CanvasEditor/commands/LassoCutoutCommand.bak.js index 8897a6bd..5c4a50b2 100644 --- a/src/component/Canvas/CanvasEditor/commands/LassoCutoutCommand.bak.js +++ b/src/component/Canvas/CanvasEditor/commands/LassoCutoutCommand.bak.js @@ -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, diff --git a/src/component/Canvas/CanvasEditor/commands/LassoCutoutCommand.js b/src/component/Canvas/CanvasEditor/commands/LassoCutoutCommand.js index 06a3ade1..a3ad1eaf 100644 --- a/src/component/Canvas/CanvasEditor/commands/LassoCutoutCommand.js +++ b/src/component/Canvas/CanvasEditor/commands/LassoCutoutCommand.js @@ -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; // 设置新组图层为活动图层 diff --git a/src/component/Canvas/CanvasEditor/commands/LayerCommands.js b/src/component/Canvas/CanvasEditor/commands/LayerCommands.js index 97f551be..cec13748 100644 --- a/src/component/Canvas/CanvasEditor/commands/LayerCommands.js +++ b/src/component/Canvas/CanvasEditor/commands/LayerCommands.js @@ -70,7 +70,7 @@ export class AddLayerCommand extends Command { undo() { // 从图层列表删除该图层 - this.layers.value = this.beforeLayers; + this.layers.value = [...this.beforeLayers]; // 恢复原活动图层 this.activeLayerId.value = this.oldActiveLayerId; @@ -116,7 +116,7 @@ export class AddLayerCommand extends Command { parentLayer.children.splice(insertIndex, 0, newLayer); console.log( - `新图层已插入到子图层位置: ${insertIndex} (父图层: ${parentLayer.name})` + `新图层已插入到子图层位置: ${insertIndex} (父图层: ${parentLayer.name})` ); } else { // 当前激活图层是一级图层 @@ -528,6 +528,7 @@ export class RemoveLayerCommand extends Command { this.layerIndex = this.layers.value.findIndex( (layer) => layer.id === this.layerId ); + this.removedLayer = this.layers.value[this.layerIndex]; this.isActiveLayer = this.layerId === this.activeLayerId.value; @@ -563,7 +564,12 @@ export class RemoveLayerCommand extends Command { allObjects.push(object); } } - + layer.fabricObjects?.forEach((fabric) => { + const { object } = findObjectById(this.canvas, fabric.id); + if (object && !allObjects.includes(object)) { + allObjects.push(object); + } + }); // 递归收集子图层的对象 if (layer.children && Array.isArray(layer.children)) { layer.children.forEach((childLayer) => { @@ -588,6 +594,9 @@ export class RemoveLayerCommand extends Command { } }); + this.layerIndex = this.layers.value.findIndex( + (layer) => layer.id === this.layerId + ); // 从图层列表中删除 this.layers.value.splice(this.layerIndex, 1); @@ -599,6 +608,9 @@ export class RemoveLayerCommand extends Command { ); if (newActiveLayer) { this.activeLayerId.value = newActiveLayer.id; + if(this.canvas.toolId === OperationType.SELECT){ + this.layerManager.selectLayerObjects(newActiveLayer.id); + } } else { this.activeLayerId.value = null; } @@ -609,7 +621,7 @@ export class RemoveLayerCommand extends Command { // this.canvas.renderAll(); // } await this.layerManager?.updateLayersObjectsInteractivity?.(); - // this.canvas.renderAll(); + this.canvas.renderAll(); console.log( `✅ 已移除图层: ${this.removedLayer.name} (ID: ${this.layerId}),包含 ${this.originalObjects.length} 个对象` @@ -2013,7 +2025,7 @@ export class LayerObjectsToGroupCommand extends Command { console.error("图层或Canvas未初始化"); return null; } - + this.activeLayer = this.layerManager.getActiveLayer(); // 查找图层中是否已有组对象 const existingGroup = this._findExistingGroup(); this.existingGroupId = existingGroup?.id || null; @@ -2053,7 +2065,7 @@ export class LayerObjectsToGroupCommand extends Command { } try { - await optimizeCanvasRendering(this.canvas, () => { + await optimizeCanvasRendering(this.canvas, async () => { if (existingGroup) { // 向现有组添加对象 this._addObjectsToExistingGroup(existingGroup, newObjectsToAdd); @@ -2064,13 +2076,13 @@ export class LayerObjectsToGroupCommand extends Command { this._createNewGroupWithAllObjects(newObjectsToAdd); this.groupObjectId = this.newGroupId; this.wasGroupCreated = true; + await this.layerManager?.layerSort?.rearrangeObjects(); } - // 更新交互性 - this.layerManager?.updateLayersObjectsInteractivity?.(false); - - // 更新缩略图 - this._updateThumbnail(); + this.layerManager?.updateLayersObjectsInteractivity?.(false).then(()=>{ + // 更新缩略图 + this._updateThumbnail(); + }); }); // 标记为非首次执行 @@ -2220,7 +2232,7 @@ export class LayerObjectsToGroupCommand extends Command { async undo() { if (!this.activeLayer || !this.canvas || !this.groupObjectId) return; - + this.activeLayer = this.layerManager.getActiveLayer(); try { await optimizeCanvasRendering(this.canvas, async () => { if (this.wasGroupCreated) { @@ -2338,7 +2350,7 @@ export class LayerObjectsToGroupCommand extends Command { // 将对象添加回画布 this.canvas.add(obj); - restoredObjects.push(obj); + restoredObjects.push(obj.toObject("id", "layerId", "layerName")); console.log( `✅ 恢复原始对象 ${obj.id || obj.type} 到位置 (${position.left}, ${ @@ -2537,9 +2549,9 @@ export class LayerObjectsToGroupCommand extends Command { * @private */ _updateThumbnail() { - // this.canvas?.thumbnailManager?.generateLayerThumbnail?.( - // this.activeLayer.id - // ); + this.canvas?.thumbnailManager?.generateLayerThumbnail?.( + this.activeLayer.id + ); } getInfo() { @@ -2569,7 +2581,6 @@ export class CreateImageLayerCommand extends Command { this.fabricImage = options.fabricImage; this.toolManager = options.toolManager; this.layerName = options.layerName || null; - this.imageId = generateId("image_"); // 存储执行过程中的结果 @@ -2591,7 +2602,7 @@ export class CreateImageLayerCommand extends Command { // 生成图层名称 const fileName = - this.layerName || `图片 ${new Date().toLocaleTimeString()}`; + this.layerName || `${new Date().toLocaleTimeString()}`; this.fabricImage.set({ id: this.imageId, @@ -2617,6 +2628,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 +4220,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; }); } diff --git a/src/component/Canvas/CanvasEditor/commands/LiquifyCommands.js b/src/component/Canvas/CanvasEditor/commands/LiquifyCommands.js index d6106c8b..2ecda7b1 100644 --- a/src/component/Canvas/CanvasEditor/commands/LiquifyCommands.js +++ b/src/component/Canvas/CanvasEditor/commands/LiquifyCommands.js @@ -1,5 +1,7 @@ import { Command, FunctionCommand } from "./Command"; import { getLiquifyReferenceManager } from "../managers/LiquifyReferenceManager"; +import { optimizeCanvasRendering } from "../utils/helper"; +import { fabric } from "fabric-with-all"; /** * 液化命令基类 @@ -59,9 +61,7 @@ export class LiquifyCommand extends Command { // 更新画布上的对象 await this._updateObjectWithResult(); - - // 刷新Canvas - this.canvas.renderAll(); + // 注意:_updateObjectWithResult 内部已使用 optimizeCanvasRendering,会自动渲染 return this.resultData; } @@ -130,6 +130,7 @@ export class LiquifyCommand extends Command { /** * 使用变形结果更新对象 + * 优化:直接使用 setElement 更新现有对象,避免创建新对象和替换操作 * @private */ async _updateObjectWithResult() { @@ -142,48 +143,103 @@ export class LiquifyCommand extends Command { const tempCtx = tempCanvas.getContext("2d"); tempCtx.putImageData(this.resultData, 0, 0); console.log("临时Canvas创建成功 _updateObjectWithResult", this.resultData); - // 更新Fabric图像 - await new Promise((resolve) => { - fabric.Image.fromURL(tempCanvas.toDataURL(), (img) => { - // 保留原对象的属性 - img.set({ - left: this.targetObject.left, - top: this.targetObject.top, - scaleX: this.targetObject.scaleX, - scaleY: this.targetObject.scaleY, - angle: this.targetObject.angle, - flipX: this.targetObject.flipX, - flipY: this.targetObject.flipY, - opacity: this.targetObject.opacity, - }); - - // 替换Canvas上的对象 - const index = this.canvas.getObjects().indexOf(this.targetObject); - if (index !== -1) { - this.canvas.remove(this.targetObject); - this.canvas.insertAt(img, index); - this.targetObject = img; - } - - // 确保图层引用更新 - const layer = this.layerManager.getLayerById(this.targetLayerId); - if (layer) { - if (layer.type === "background" && layer.fabricObject === this.targetObject) { - layer.fabricObject = img; - } else if (layer.fabricObjects) { - const objIndex = layer.fabricObjects.indexOf(this.targetObject); - if (objIndex !== -1) { - layer.fabricObjects[objIndex] = img; - } - } - } - - resolve(); - }); + + // 使用优化渲染工具,避免图层闪烁 + await optimizeCanvasRendering(this.canvas, async () => { + // 预加载图像元素,确保完全加载后再更新 + await this._updateObjectElementDirectly(tempCanvas.toDataURL()); }); return true; } + + /** + * 直接更新对象的图像元素,避免对象替换造成的图层闪烁 + * @param {String} imageDataURL 图像数据的 DataURL + * @private + */ + async _updateObjectElementDirectly(imageDataURL) { + return new Promise((resolve, reject) => { + // 创建 HTMLImageElement 并预加载 + const imgElement = new Image(); + + imgElement.onload = () => { + try { + // 保存当前对象状态(非图像属性) + const currentState = { + left: this.targetObject.left, + top: this.targetObject.top, + scaleX: this.targetObject.scaleX, + scaleY: this.targetObject.scaleY, + angle: this.targetObject.angle, + flipX: this.targetObject.flipX, + flipY: this.targetObject.flipY, + opacity: this.targetObject.opacity, + }; + + // 直接更新现有对象的图像元素,保持对象引用不变 + if (this.targetObject.setElement) { + this.targetObject.setElement(imgElement); + } else if (this.targetObject._element) { + this.targetObject._element = imgElement; + this.targetObject._originalElement = imgElement; + } + + // 恢复对象属性(setElement 可能会重置一些属性) + this.targetObject.set(currentState); + + // 标记对象需要重新渲染 + this.targetObject.dirty = true; + this.targetObject.setCoords(); + + resolve(); + } catch (error) { + console.error("更新对象元素失败:", error); + reject(error); + } + }; + + imgElement.onerror = () => { + reject(new Error("图像加载失败")); + }; + + // 开始加载图像 + imgElement.src = imageDataURL; + }); + } + + /** + * 安全地替换对象,避免图层闪烁(保留作为备用方法) + * @param {Object} newImg 新的fabric图像对象 + * @private + */ + _replaceObjectSafely(newImg) { + // 保存旧对象引用,用于更新图层引用 + const oldObject = this.targetObject; + + // 替换Canvas上的对象 + const index = this.canvas.getObjects().indexOf(oldObject); + if (index !== -1) { + // 在禁用自动渲染的情况下,先插入新对象,再移除旧对象 + // 这样可以避免中间出现空白(因为renderOnAddRemove已被禁用) + this.canvas.insertAt(newImg, index); + this.canvas.remove(oldObject); + this.targetObject = newImg; + } + + // 确保图层引用更新 + const layer = this.layerManager.getLayerById(this.targetLayerId); + if (layer) { + if (layer.type === "background" && layer.fabricObject === oldObject) { + layer.fabricObject = newImg; + } else if (layer.fabricObjects) { + const objIndex = layer.fabricObjects.indexOf(oldObject); + if (objIndex !== -1) { + layer.fabricObjects[objIndex] = newImg; + } + } + } + } } /** @@ -271,8 +327,8 @@ export class LiquifyDeformCommand extends LiquifyCommand { // 应用变形结果 await this._updateObjectWithImageData(this.afterData); + // 注意:_updateObjectWithImageData 内部已使用 optimizeCanvasRendering,会自动渲染 - this.canvas.renderAll(); return this.afterData; } @@ -283,70 +339,70 @@ export class LiquifyDeformCommand extends LiquifyCommand { // 恢复到变形前的状态 await this._updateObjectWithImageData(this.beforeData); + // 注意:_updateObjectWithImageData 内部已使用 optimizeCanvasRendering,会自动渲染 - this.canvas.renderAll(); return true; } /** * 使用图像数据更新对象 + * 优化:直接使用 setElement 更新现有对象,避免创建新对象和替换操作 * @param {ImageData} imageData 图像数据 * @private */ async _updateObjectWithImageData(imageData) { - return new Promise((resolve) => { - // 创建临时canvas - const tempCanvas = document.createElement("canvas"); - tempCanvas.width = imageData.width; - tempCanvas.height = imageData.height; - const tempCtx = tempCanvas.getContext("2d"); - tempCtx.putImageData(imageData, 0, 0); + // 创建临时canvas + const tempCanvas = document.createElement("canvas"); + tempCanvas.width = imageData.width; + tempCanvas.height = imageData.height; + const tempCtx = tempCanvas.getContext("2d"); + tempCtx.putImageData(imageData, 0, 0); - // 从canvas创建新的fabric图像 - fabric.Image.fromURL(tempCanvas.toDataURL(), (img) => { - // 保留原对象的变换属性 - img.set({ - left: this.targetObject.left, - top: this.targetObject.top, - scaleX: this.targetObject.scaleX, - scaleY: this.targetObject.scaleY, - angle: this.targetObject.angle, - flipX: this.targetObject.flipX, - flipY: this.targetObject.flipY, - opacity: this.targetObject.opacity, - }); - - // 替换canvas上的对象 - const index = this.canvas.getObjects().indexOf(this.targetObject); - if (index !== -1) { - this.canvas.remove(this.targetObject); - this.canvas.insertAt(img, index); - this.targetObject = img; - - // 更新图层引用 - const layer = this.layerManager.getLayerById(this.targetLayerId); - if (layer) { - if ( - layer.type === "background" && - (layer.fabricObject === this.savedState?.originalObject || - layer.fabricObject === this.targetObject) - ) { - layer.fabricObject = img; - } else if (layer.fabricObjects) { - const objIndex = layer.fabricObjects.findIndex( - (obj) => obj === this.savedState?.originalObject || obj === this.targetObject - ); - if (objIndex !== -1) { - layer.fabricObjects[objIndex] = img; - } - } - } - } - - resolve(); - }); + // 使用优化渲染工具,避免图层闪烁 + await optimizeCanvasRendering(this.canvas, async () => { + // 直接更新对象元素,避免对象替换 + await this._updateObjectElementDirectly(tempCanvas.toDataURL()); }); } + + /** + * 安全地替换变形对象,避免图层闪烁(保留作为备用方法) + * @param {Object} newImg 新的fabric图像对象 + * @private + */ + _replaceDeformObjectSafely(newImg) { + // 保存旧对象引用,用于更新图层引用 + const oldObject = this.targetObject; + + // 替换Canvas上的对象 + const index = this.canvas.getObjects().indexOf(oldObject); + if (index !== -1) { + // 在禁用自动渲染的情况下,先插入新对象,再移除旧对象 + // 这样可以避免中间出现空白 + this.canvas.insertAt(newImg, index); + this.canvas.remove(oldObject); + this.targetObject = newImg; + } + + // 更新图层引用 + const layer = this.layerManager.getLayerById(this.targetLayerId); + if (layer) { + if ( + layer.type === "background" && + (layer.fabricObject === this.savedState?.originalObject || + layer.fabricObject === oldObject) + ) { + layer.fabricObject = newImg; + } else if (layer.fabricObjects) { + const objIndex = layer.fabricObjects.findIndex( + (obj) => obj === this.savedState?.originalObject || obj === oldObject + ); + if (objIndex !== -1) { + layer.fabricObjects[objIndex] = newImg; + } + } + } + } } /** diff --git a/src/component/Canvas/CanvasEditor/commands/ObjectLayerCommands.js b/src/component/Canvas/CanvasEditor/commands/ObjectLayerCommands.js index d9b60f4a..1243295a 100644 --- a/src/component/Canvas/CanvasEditor/commands/ObjectLayerCommands.js +++ b/src/component/Canvas/CanvasEditor/commands/ObjectLayerCommands.js @@ -255,6 +255,8 @@ export class AddObjectToLayerCommand extends Command { ); // 标记为非首次执行 this.isFirstExecution = false; + // 重新排序图层对象 + await this.layerManager?.layerSort?.rearrangeObjects(); console.log( `✅ 对象已添加到图层 "${layer.name}",位置: (${this.fabricObject.left}, ${this.fabricObject.top})` ); diff --git a/src/component/Canvas/CanvasEditor/commands/RasterizeLayerCommand.js b/src/component/Canvas/CanvasEditor/commands/RasterizeLayerCommand.js index 3e9731aa..54c6285b 100644 --- a/src/component/Canvas/CanvasEditor/commands/RasterizeLayerCommand.js +++ b/src/component/Canvas/CanvasEditor/commands/RasterizeLayerCommand.js @@ -15,6 +15,8 @@ import { import { createRasterizedImage } from "../utils/rasterizedImage"; import { message } from "ant-design-vue"; import { restoreFabricObject } from "../utils/objectHelper"; +import i18n from "@/lang/index.ts"; +const { t } = i18n.global; /** * 组合图层命令 @@ -338,12 +340,12 @@ export class RasterizeLayerCommand extends Command { // 创建新的组合图层 this.rasterizedLayer = createLayer({ id: this.rasterizedLayerId, - name: `${this.layer.name} (组合)`, + name: `${this.layer.name} (${t('Canvas.group')})`, type: LayerType.BITMAP, visible: this.layer.visible, locked: this.layer.locked, opacity: this.layer.opacity, - fabricObjects: [rasterizedImage], + fabricObjects: [], }); // 更新图像对象的图层关联 @@ -353,13 +355,14 @@ export class RasterizeLayerCommand extends Command { layerId: this.rasterizedLayerId, layerName: this.rasterizedLayer.name, }); - + this.rasterizedLayer.fabricObjects = [rasterizedImage.toObject(["id", "layerId", "layerName"])] // 在适当位置添加新的组合图层 this._replaceLayerInStructure(); // 设置为活动图层 this.activeLayerId.value = this.rasterizedLayerId; - + // 重新排序图层对象 + await this.layerManager?.layerSort?.rearrangeObjects(); await this.layerManager?.updateLayersObjectsInteractivity(false); console.log(`🎨 组合图层 ${this.rasterizedLayer.name} 创建完成`); @@ -490,7 +493,7 @@ export class ExportLayerToImageCommand extends Command { this._collectLayersAndObjects(); } - async execute() { + async execute(isDownload = true) { if (!this.layer) { throw new Error(`图层 ${this.layerId} 不存在`); } @@ -529,18 +532,21 @@ export class ExportLayerToImageCommand extends Command { fabricObjects: this.objectsToRasterize, isReturenDataURL: true, maskObject: clippingMaskFabricObject || null, // 不处理遮罩 + scaleFactor: isDownload ? 2 : 1, }); + // 模拟浏览器下载 - const link = document.createElement("a"); - link.href = imageBase64; - link.download = `${this.layer.name}.png`; - document.body.appendChild(link); - link.click(); - document.body.removeChild(link); - + if (isDownload) { + const link = document.createElement("a"); + link.href = imageBase64; + link.download = `${this.layer.name}.png`; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + } console.log(`✅ 图层 ${this.layer.name} 导出完成`); - return true; + return imageBase64; } catch (error) { console.error("导出图层失败:", error); throw error; diff --git a/src/component/Canvas/CanvasEditor/commands/TextCommands.js b/src/component/Canvas/CanvasEditor/commands/TextCommands.js index f4d52013..8e6c80c0 100644 --- a/src/component/Canvas/CanvasEditor/commands/TextCommands.js +++ b/src/component/Canvas/CanvasEditor/commands/TextCommands.js @@ -1,6 +1,8 @@ -import { generateId, optimizeCanvasRendering } from "../utils/helper"; +import { generateId, optimizeCanvasRendering, getLayerObjectsZIndex } from "../utils/helper"; import { createLayer, LayerType, OperationType } from "../utils/layerHelper"; import { Command } from "./Command"; +import i18n from "@/lang/index.ts"; +const { t } = i18n.global; /** * 文本内容命令 @@ -319,6 +321,7 @@ export class CreateTextCommand extends Command { this.x = options.x; this.y = options.y; this.textOptions = options.textOptions || {}; + this.options = options; // 生成唯一ID this.textId = options?.textId || generateId("text_"); this.layerId = options?.layerId || generateId("text_layer_"); @@ -329,7 +332,7 @@ export class CreateTextCommand extends Command { // 默认文本属性 this.defaultOptions = { - text: "双击编辑文本", + text: options.text || t('Canvas.DoubleClickText'), fontFamily: "Arial", fontSize: 24, fontWeight: "normal", @@ -371,8 +374,8 @@ export class CreateTextCommand extends Command { originY: "center", }); - // 创建文本图层 - const layerName = this.textOptions.layerName || "文本图层"; + // 创建文本图层 取15 + const layerName = this.options.text?.substring(0, 25) || t('Canvas.TextLayer'); const layer = createLayer({ id: this.layerId, name: layerName, @@ -407,6 +410,9 @@ export class CreateTextCommand extends Command { // 现在可以安全地设置为活动图层 this.layerManager.setActiveLayer(this.layerId); + // 重新排序图层对象 + await this.layerManager?.layerSort?.rearrangeObjects(); + // 更新对象交互性 await this.layerManager?.updateLayersObjectsInteractivity?.(false); @@ -534,6 +540,12 @@ export class CreateTextCommand extends Command { if (this.textObject && this.canvas) { this.canvas.remove(this.textObject); } + const layerObjects = getLayerObjectsZIndex(this.canvas, this.layerId); + layerObjects.forEach((obj) => { + if (obj.id === this.textObject?.id) { + this.canvas.remove(obj.object); + } + }); // 智能移除创建的图层 if (this.layerId && this.layerManager) { diff --git a/src/component/Canvas/CanvasEditor/components/BrushControlPanel.vue b/src/component/Canvas/CanvasEditor/components/BrushControlPanel.vue index 3d08bb67..310b6a60 100644 --- a/src/component/Canvas/CanvasEditor/components/BrushControlPanel.vue +++ b/src/component/Canvas/CanvasEditor/components/BrushControlPanel.vue @@ -362,6 +362,11 @@ watch( setBrushSize(newSize); } ); +watch(()=>isVisible.value, (newVisible) => { + if (newVisible) { + setBrushSize(brushSize.value); + } +}) // 监听brushOpacity的变化,更新到BrushStore watch( @@ -483,7 +488,7 @@ watch( display: flex; justify-content: center; align-items: center; - background: repeating-conic-gradient(#f5f5f5 0% 25%, #ffffff 0% 50%) 50% / 10px 10px; + background: repeating-conic-gradient(#F9FAFA 0% 25%, #ffffff 0% 50%) 50% / 10px 10px; border-radius: 6px; box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1); margin-bottom: 5px; @@ -513,7 +518,7 @@ watch( left: 0; width: 100%; height: 100%; - background: repeating-conic-gradient(#f5f5f5 0% 25%, #ffffff 0% 50%) 50% / 10px 10px; + background: repeating-conic-gradient(#F9FAFA 0% 25%, #ffffff 0% 50%) 50% / 10px 10px; } .opacity-color { @@ -537,7 +542,7 @@ watch( font-size: 14px; font-weight: 500; color: #333; - background: #f5f5f5; + background: #F9FAFA; padding: 2px 8px; border-radius: 4px; min-width: 50px; diff --git a/src/component/Canvas/CanvasEditor/components/BrushPanel.vue b/src/component/Canvas/CanvasEditor/components/BrushPanel.vue index f78e5935..9d0aab2c 100644 --- a/src/component/Canvas/CanvasEditor/components/BrushPanel.vue +++ b/src/component/Canvas/CanvasEditor/components/BrushPanel.vue @@ -190,7 +190,7 @@
- {{ $t("上传的纹理") }} + {{ $t("Canvas.UploadedTexture") }}
@@ -201,7 +201,7 @@
+
- {{ $t("上传纹理") }} + {{ $t("Canvas.UploadTexture") }}
×
@@ -535,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"); @@ -873,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); // 应用新创建的预设(可选) @@ -1935,7 +1938,7 @@ const brushStore = BrushStore; } .shadow-preview-box { - background: repeating-conic-gradient(#f5f5f5 0% 25%, #ffffff 0% 50%) 50% / 10px 10px; + background: repeating-conic-gradient(#F9FAFA 0% 25%, #ffffff 0% 50%) 50% / 10px 10px; border-radius: 8px; padding: 30px; display: flex; diff --git a/src/component/Canvas/CanvasEditor/components/CropImage.vue b/src/component/Canvas/CanvasEditor/components/CropImage.vue new file mode 100644 index 00000000..6eb5d7b7 --- /dev/null +++ b/src/component/Canvas/CanvasEditor/components/CropImage.vue @@ -0,0 +1,695 @@ + + + + + diff --git a/src/component/Canvas/CanvasEditor/components/HeaderMenu.vue b/src/component/Canvas/CanvasEditor/components/HeaderMenu.vue index 2b5d104a..675c9db4 100644 --- a/src/component/Canvas/CanvasEditor/components/HeaderMenu.vue +++ b/src/component/Canvas/CanvasEditor/components/HeaderMenu.vue @@ -21,6 +21,7 @@ const props = defineProps({ type: Boolean, default: true, // 是否显示图层面板 }, + isBackgroundChangeable: Boolean, }); const emit = defineEmits([ @@ -312,7 +313,7 @@ onMounted(() => { " /> -
+
{{ $t("Canvas.color") }}
iPad iOS Android - 其他 - (触控设备) + {{ $t('Canvas.other') }} + ({{ $t('Canvas.touchDevice') }})
@@ -421,14 +421,14 @@ function getShortcutsByCategory(category) {
-->
-

触控设备提示

+

{{ $t('Canvas.touchDevicePrompts') }}

    -
  • 长按图层面板可访问更多选项
  • -
  • 双击元素可快速进入编辑模式
  • -
  • 双指拖动可平移画布
  • -
  • 双指捏合可缩放画布
  • -
  • 双指连按可显示元素变换控制点
  • -
  • 三指左右滑动可进行撤销/重做操作
  • +
  • {{ $t('Canvas.touchDevicePrompts_1') }}
  • +
  • {{ $t('Canvas.touchDevicePrompts_2') }}
  • +
  • {{ $t('Canvas.touchDevicePrompts_3') }}
  • +
  • {{ $t('Canvas.touchDevicePrompts_4') }}
  • +
  • {{ $t('Canvas.touchDevicePrompts_5') }}
  • +
  • {{ $t('Canvas.touchDevicePrompts_6') }}
@@ -484,7 +484,7 @@ h3 { } .shortcuts-table th { - background-color: #f5f5f5; + background-color: #F9FAFA; } .touch-tips { diff --git a/src/component/Canvas/CanvasEditor/components/LayersPanel/LayersPanel.vue b/src/component/Canvas/CanvasEditor/components/LayersPanel/LayersPanel.vue index 5d05111c..b6971bb3 100644 --- a/src/component/Canvas/CanvasEditor/components/LayersPanel/LayersPanel.vue +++ b/src/component/Canvas/CanvasEditor/components/LayersPanel/LayersPanel.vue @@ -589,11 +589,11 @@ function handleLayerClick(layer, event) { layerManager?.setAllActiveGroupLayerCanvasObject?.(layer); setActiveLayer(layer.children[0].id, { parentId: layer.id }); } else { + // 选中画布中的图层对象 + layerManager?.selectLayerObjects(layer.id); // 否则直接设置当前图层为活动图层 setActiveLayer(layer.id); layerManager?.updateLayersObjectsInteractivity(); - // 选中画布中的图层对象 - layerManager?.selectLayerObjects(layer.id); } } lastSelectedIndex.value = sortableRootLayers.value.findIndex((l) => l.id === layer.id); diff --git a/src/component/Canvas/CanvasEditor/components/LayersPanel/contextMenu.less b/src/component/Canvas/CanvasEditor/components/LayersPanel/contextMenu.less index 305571dd..dcfe0296 100644 --- a/src/component/Canvas/CanvasEditor/components/LayersPanel/contextMenu.less +++ b/src/component/Canvas/CanvasEditor/components/LayersPanel/contextMenu.less @@ -42,7 +42,7 @@ position: relative; &:hover:not(.disabled) { - background-color: #f5f5f5; + background-color: #F9FAFA; } &:active:not(.disabled) { @@ -76,7 +76,7 @@ } &.hovered { - background-color: #f5f5f5; + background-color: #F9FAFA; } } diff --git a/src/component/Canvas/CanvasEditor/components/LayersPanel/layersPanel.css b/src/component/Canvas/CanvasEditor/components/LayersPanel/layersPanel.css index 97a58719..232a2738 100644 --- a/src/component/Canvas/CanvasEditor/components/LayersPanel/layersPanel.css +++ b/src/component/Canvas/CanvasEditor/components/LayersPanel/layersPanel.css @@ -10,7 +10,7 @@ z-index: 6; overflow-y: auto; height: 100%; - max-height: 85vh; + max-height: 70vh; -webkit-overflow-scrolling: touch; } .layers-header { @@ -61,12 +61,12 @@ .action-btn[disabled] { opacity: 0.5; cursor: not-allowed; - background-color: #f5f5f5; + background-color: #F9FAFA; color: #bfbfbf; border-color: #e6e6e6; } .action-btn[disabled]:hover { - background-color: #f5f5f5; + background-color: #F9FAFA; color: #bfbfbf; border-color: #e6e6e6; } @@ -196,7 +196,7 @@ justify-content: center; overflow: hidden; flex: none; - background: repeating-conic-gradient(#f5f5f5 0% 25%, #ffffff 0% 50%) 50% / 1rem 1rem; + background: repeating-conic-gradient(#F9FAFA 0% 25%, #ffffff 0% 50%) 50% / 1rem 1rem; border: 1px solid #e0e0e0; } .layer-thumbnail { diff --git a/src/component/Canvas/CanvasEditor/components/LayersPanel/layersPanel.less b/src/component/Canvas/CanvasEditor/components/LayersPanel/layersPanel.less index 2229c0b1..e90cbe5a 100644 --- a/src/component/Canvas/CanvasEditor/components/LayersPanel/layersPanel.less +++ b/src/component/Canvas/CanvasEditor/components/LayersPanel/layersPanel.less @@ -12,8 +12,8 @@ user-select: none; z-index: 6; overflow-y: auto; - height: 100%; - max-height: 85vh; + width: 100%; + // max-height: 70vh; -webkit-overflow-scrolling: touch; } @@ -72,12 +72,12 @@ &[disabled] { opacity: 0.5; cursor: not-allowed; - background-color: #f5f5f5; + background-color: #F9FAFA; color: #bfbfbf; border-color: #e6e6e6; &:hover { - background-color: #f5f5f5; + background-color: #F9FAFA; color: #bfbfbf; border-color: #e6e6e6; } @@ -244,7 +244,7 @@ justify-content: center; overflow: hidden; flex: none; - background: repeating-conic-gradient(#f5f5f5 0% 25%, #ffffff 0% 50%) 50% / + background: repeating-conic-gradient(#F9FAFA 0% 25%, #ffffff 0% 50%) 50% / 1rem 1rem; border: 1px solid #e0e0e0; } @@ -586,7 +586,7 @@ // 响应式设计 @media (max-width: 768px) { .layers-panel-inner { - max-height: 70vh; + // max-height: 70vh; } .layer-item { diff --git a/src/component/Canvas/CanvasEditor/components/LiquifyPanel.vue b/src/component/Canvas/CanvasEditor/components/LiquifyPanel.vue index b58f52fb..9e77c0e2 100644 --- a/src/component/Canvas/CanvasEditor/components/LiquifyPanel.vue +++ b/src/component/Canvas/CanvasEditor/components/LiquifyPanel.vue @@ -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("未选择有效图像或图层不适合液化操作"); @@ -519,7 +537,7 @@ function showPanel(event) { } visible.value = true; - closePanel.value = true +// closePanel.value = true isEditing.value = true; // 初始化液化管理器并准备液化环境 @@ -1634,24 +1652,27 @@ 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; + height: 22px; + + > i{ + font-size: 1.4rem; + transform: rotate(270deg); + } } } diff --git a/src/component/Canvas/CanvasEditor/components/SelectMenuPanel.vue b/src/component/Canvas/CanvasEditor/components/SelectMenuPanel.vue new file mode 100644 index 00000000..c2b5755f --- /dev/null +++ b/src/component/Canvas/CanvasEditor/components/SelectMenuPanel.vue @@ -0,0 +1,744 @@ + + + + + diff --git a/src/component/Canvas/CanvasEditor/components/SelectionPanel.vue b/src/component/Canvas/CanvasEditor/components/SelectionPanel.vue index 31bd74b6..2f1403b3 100644 --- a/src/component/Canvas/CanvasEditor/components/SelectionPanel.vue +++ b/src/component/Canvas/CanvasEditor/components/SelectionPanel.vue @@ -145,10 +145,10 @@
@@ -159,7 +159,7 @@
-

{{ $t("选择填充颜色") }}

+

{{ $t("Canvas.SelectFillColor") }}

@@ -168,10 +168,10 @@
@@ -531,10 +531,13 @@ function confirmColorPicker() { width: 100%; text-align: center; cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + height: 22px; > i{ font-size: 1.4rem; - display: block; transform: rotate(270deg); } } diff --git a/src/component/Canvas/CanvasEditor/components/TextEditorPanel.vue b/src/component/Canvas/CanvasEditor/components/TextEditorPanel.vue index 20f786dd..2c01a627 100644 --- a/src/component/Canvas/CanvasEditor/components/TextEditorPanel.vue +++ b/src/component/Canvas/CanvasEditor/components/TextEditorPanel.vue @@ -619,10 +619,20 @@ export default { onMounted(() => { // 监听显示文本编辑面板事件 document.addEventListener("showTextEditor", showEditor); + document.addEventListener("hideTextEditor", close); + if(props.canvas) { + // props.canvas.on("text:editing:entered", showEditor); + props.canvas.on("text:editing:exited", close); + } }); onUnmounted(() => { document.removeEventListener("showTextEditor", showEditor); + document.removeEventListener("hideTextEditor", close); + if(props.canvas) { + // props.canvas.off("text:editing:entered", showEditor); + props.canvas.off("text:editing:exited", close); + } }); // 返回所有需要在模板中使用的数据和方法 @@ -715,7 +725,10 @@ export default { width: 100%; text-align: center; cursor: pointer; - + display: flex; + align-items: center; + justify-content: center; + height: 22px; > i{ font-size: 1.4rem; display: block; diff --git a/src/component/Canvas/CanvasEditor/components/ToolsSidebar.vue b/src/component/Canvas/CanvasEditor/components/ToolsSidebar.vue index 21762558..8e0361c4 100644 --- a/src/component/Canvas/CanvasEditor/components/ToolsSidebar.vue +++ b/src/component/Canvas/CanvasEditor/components/ToolsSidebar.vue @@ -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(); @@ -296,11 +327,14 @@ function handleKeyDown(event) { } } +const fillInputTimeout = ref(null); // 填充颜色选择器 function fillColorChange() { - layerManager.fillLayerBackground(lastSelectLayerId.value, fillColor.value, true); + clearTimeout(fillInputTimeout.value); + fillInputTimeout.value = setTimeout(() => { + layerManager.fillLayerBackground(lastSelectLayerId.value, fillColor.value, true); + }, 100); } - onMounted(() => { // 添加键盘事件监听 window.addEventListener("keydown", handleKeyDown); @@ -324,25 +358,28 @@ const handleToolClick = (tool) => { v-model="fillColor" ref="fillColorRef" type="color" - @change="fillColorChange" + @input="fillColorChange" style="width: 0; height: 0; opacity: 0" /> - - +
+ - + - - + + +
+
@@ -350,17 +387,31 @@ 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; + position: relative; /* overflow-y: auto; */ /* overflow-x: hidden; */ } - +.fillColor-input{ + position: absolute; + top: 0; + right: 0; +} +.tools-list{ + display: flex; + flex-direction: column; + gap: 0.5rem; + flex: 1; + overflow-y: auto; + overflow-x: hidden; +} .red-green-mode { background-color: #fff4f4; } diff --git a/src/component/Canvas/CanvasEditor/components/css/layersPanel.css b/src/component/Canvas/CanvasEditor/components/css/layersPanel.css new file mode 100644 index 00000000..047214da --- /dev/null +++ b/src/component/Canvas/CanvasEditor/components/css/layersPanel.css @@ -0,0 +1,656 @@ +.text-ellipsis { + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; +} +.layers-panel-inner { + display: flex; + flex-direction: column; + user-select: none; + z-index: 6; + overflow-y: auto; + width: 100%; + -webkit-overflow-scrolling: touch; +} +.layers-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 1.5rem; + border-bottom: 1px solid #e0e0e0; +} +.layers-header h3 { + margin: 0; + font-size: 1.6rem; + font-weight: 500; + color: #333; +} +.layer-actions-group { + display: flex; + gap: 0.8rem; +} +.layer-actions-group .normal-actions, +.layer-actions-group .multi-select-actions { + display: flex; + gap: 0.8rem; +} +.action-btn { + width: 3.2rem; + height: 3.2rem; + background: none; + border: 1px solid #d9d9d9; + border-radius: 0.4rem; + display: flex; + align-items: center; + justify-content: center; + color: #666; + cursor: pointer; + transition: all 0.2s ease; +} +.action-btn:hover { + background-color: #f0f0f0; + border-color: #40a9ff; + color: #40a9ff; +} +.action-btn:active { + background-color: #e6f7ff; + border-color: #1890ff; + color: #1890ff; +} +.action-btn[disabled] { + opacity: 0.5; + cursor: not-allowed; + background-color: #F9FAFA; + color: #bfbfbf; + border-color: #e6e6e6; +} +.action-btn[disabled]:hover { + background-color: #F9FAFA; + color: #bfbfbf; + border-color: #e6e6e6; +} +.group-btn { + background-color: #e6f7ff; + border-color: #91d5ff; + color: #1890ff; +} +.group-btn:hover { + background-color: #bae7ff; + border-color: #69c0ff; +} +.group-btn.disabled { + background-color: #f0f5ff; + border-color: #d9ecff; + color: #bfbfbf; +} +.ungroup-btn { + background-color: #fff2e8; + border-color: #ffbb96; + color: #fa8c16; +} +.ungroup-btn:hover { + background-color: #ffd8bf; + border-color: #ff9c6e; + color: #fa8c16; +} +.ungroup-btn.disabled { + background-color: #f0f5ff; + border-color: #d9ecff; + color: #bfbfbf; +} +.delete-selected-btn { + background-color: #fff2f0; + border-color: #ffccc7; + color: #ff4d4f; +} +.delete-selected-btn:hover { + background-color: #ffebe6; + border-color: #ff7875; + color: #ff4d4f; +} +.clear-selection-btn { + background-color: #f6f6f6; + border-color: #d9d9d9; + color: #595959; +} +.clear-selection-btn:hover { + background-color: #e6e6e6; + border-color: #bfbfbf; + color: #595959; +} +.multi-select-info { + padding: 1rem 0.6rem; + background-color: rgba(238, 238, 238, 0.4); + border-bottom: 1px solid #91d5ff; + color: #333; + font-size: 1.3rem; + line-height: 1.4; +} +.multi-select-info small { + display: block; + margin-top: 0.4rem; + color: #666; + font-size: 1.1rem; +} +.layers-list { + position: relative; + flex: 1; + overflow-y: auto; +} +.layer-item { + position: relative; + width: 100%; + display: flex; + flex-direction: column; + padding: 1rem 0; + cursor: pointer; + transition: all 0.2s ease; + border: 1px solid transparent; + border-left: 0; + border-right: 0; + border: none; + border-bottom: 1px solid #f5f2f2; + padding-left: 3rem; + padding-right: 1rem; + color: #333; +} +.layer-item.group-layer { + background-color: rgba(240, 248, 255, 0.3); + border-color: #e6f7ff; +} +.layer-item:hover { + background-color: #f0f0f0; + border-color: #e0e0e0; +} +.layer-item.active { + background-color: #e6f7ff; + border-color: #91d5ff; +} +.layer-item.selected { + background-color: #bae7ff; + border-color: #91d5ff; +} +.layer-item.editing { + background-color: #fff7e6; + border-color: #ffd666; +} +.layer-item.disabled { + opacity: 0.6; + cursor: not-allowed; +} +.layer-item.disabled:hover { + background-color: transparent; +} +.layer-header { + display: flex; + align-items: center; + width: 100%; + gap: 0.6rem; +} +.layer-review { + width: 3.2rem; + height: 3.2rem; + display: flex; + align-items: center; + justify-content: center; + overflow: hidden; + flex: none; + background: repeating-conic-gradient(#F9FAFA 0% 25%, #ffffff 0% 50%) 50% / 1rem 1rem; + border: 1px solid #e0e0e0; +} +.layer-thumbnail { + width: 100%; + height: 100%; + object-fit: contain; +} +.layer-type-icon { + font-size: 1.4rem; +} +.visibility-btn { + width: 2.2rem; + height: 2.2rem; + cursor: pointer; + flex: none; + color: #333; + display: flex; + align-items: center; + justify-content: center; +} +.visibility-btn.hidden { + color: #999; +} +.layer-name-container { + flex: 1; + margin: 0 0.6rem; + overflow: hidden; +} +.layer-name-container .layer-name-wrapper { + width: 100%; + display: flex; + align-items: center; + justify-content: space-between; +} +.layer-name { + color: #333; + font-size: 1.4rem; + text-align: left; + display: block; + width: 100%; +} +.layer-name-input { + width: 100%; + padding: 0.2rem 0.4rem; + border: 1px solid #1890ff; + border-radius: 0.3rem; + font-size: 1.4rem; + color: #333; + background-color: #fff; + outline: none; + box-sizing: border-box; +} +.layer-name-input:focus { + border-color: #40a9ff; + box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2); +} +.layer-status { + display: flex; + align-items: center; + gap: 0.4rem; +} +.status-icon { + font-size: 1.2rem; +} +.status-icon.locked { + color: #1890ff; +} +.status-icon.group { + color: #fa8c16; +} +.status-icon.disabled { + color: #ccc; + cursor: not-allowed; +} +.layer-actions { + display: flex; + gap: 0.6rem; +} +.delete-btn { + font-size: 1.6rem; + cursor: pointer; + width: 2.2rem; + height: 2.2rem; + display: flex; + align-items: center; + justify-content: center; +} +.delete-btn:hover { + color: #ff4d4f; +} +.delete-btn.disabled { + color: #ccc; + cursor: not-allowed; +} +.layer-drag-handle { + position: absolute; + top: 0; + left: 0; + width: 2rem; + height: 100%; + cursor: move; + flex: none; + display: flex; + align-items: center; + justify-content: center; + color: #999; + margin-right: 0.4rem; + background: #eee; + box-shadow: 0 0 4px rgba(0, 0, 0, 0.2); +} +.layer-drag-handle:hover { + color: #333; +} +.layer-checkbox { + width: 1.8rem; + height: 1.8rem; + margin-right: 0; + cursor: pointer; + flex: none; + display: flex; + align-items: center; +} +.child-layer { + padding: 0.8rem 2rem 0.8rem 3.2rem; + background-color: rgba(240, 240, 240, 0.3); + border-left: 2px solid #e0e0e0; +} +.child-layer:hover { + background-color: rgba(224, 224, 224, 0.5); +} +.child-layer.active { + background-color: rgba(230, 247, 255, 0.5); + border-left: 2px solid #1890ff; +} +.child-layer.editing { + background-color: rgba(255, 247, 230, 0.5); + border-left: 2px solid #ffd666; +} +.child-layer .layer-actions { + position: static; + display: flex; + gap: 0.4rem; +} +.child-layer .layer-actions button { + width: 2rem; + height: 2rem; + border: none; + background: none; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + color: #999; + border-radius: 2px; + transition: all 0.2s; +} +.child-layer .layer-actions button:hover { + background-color: #f0f0f0; + color: #333; +} +.layer-indent { + width: 2rem; + flex: none; +} +.layer-info { + flex: 1; + margin: 0 0.8rem; +} +.layer-info .layer-name { + font-size: 1.3rem; + color: #333; + margin-bottom: 0.2rem; +} +.layer-info .layer-status { + display: flex; + align-items: center; + gap: 0.4rem; +} +.layer-info .layer-type { + font-size: 11px; + color: #999; +} +.child-drag-handle { + width: 1.6rem; + height: 1.6rem; + cursor: move; + flex: none; + display: flex; + align-items: center; + justify-content: center; + color: #999; + margin-right: 0.4rem; +} +.child-drag-handle:hover { + color: #333; +} +.fixed-layers { + border-top: 1px solid #e0e0e0; + background-color: rgba(238, 238, 238, 0.4); +} +.fixed-layers .layer-drag-handle { + cursor: default; +} +.fixed-layer { + background-color: #fafafa; +} +.fixed-layer-indicator { + width: 2rem; + height: 2rem; + display: flex; + align-items: center; + justify-content: center; + color: #1890ff; + margin-right: 0.4rem; +} +.background-indicator, +.fixed-indicator { + display: flex; + align-items: center; + justify-content: center; + margin-left: 0.4rem; +} +.background-icon, +.fixed-icon { + font-size: 1.4rem; + color: #999; +} +.sortable-layers { + width: 100%; +} +.ghost { + opacity: 0.5; + background-color: #f0f0f0; + border: 2px dashed #1890ff; +} +.chosen { + background-color: #e6f7ff; + border: 1px solid #1890ff; +} +.drag { + opacity: 0.8; + transform: rotate(5deg); + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); +} +.child-layers .ghost { + opacity: 0.4; + background-color: #fff7e6; + border: 1px dashed #faad14; +} +.child-layers .chosen { + background-color: #fff7e6; + border: 1px solid #faad14; +} +.child-layers .drag { + opacity: 0.7; + transform: rotate(3deg); + box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15); +} +@media (max-width: 768px) { + .layer-item { + padding: 1.2rem; + padding-left: 3.5rem; + } + .layer-header { + min-height: 4rem; + } + .layer-drag-handle, + .visibility-btn { + width: 2.4rem; + } + .layer-review { + width: 3.6rem; + height: 3.6rem; + } + .action-btn { + width: 3.6rem; + height: 3.6rem; + } + .multi-select-info small { + font-size: 1.1rem; + } +} +@media (min-width: 768px) and (max-width: 1024px) { + .layer-item { + padding: 10px; + padding-left: 30px; + } + .layer-drag-handle:hover, + .visibility-btn:hover { + background-color: rgba(0, 0, 0, 0.04); + border-radius: 4px; + } +} +@media (hover: none) and (pointer: coarse) { + .layer-item { + padding-left: 30px; + } + .layer-item:hover { + background-color: transparent; + } + .layer-item:active { + background-color: #f0f0f0; + } + .action-btn:hover { + background-color: transparent; + border-color: #d9d9d9; + color: #666; + } + .action-btn:active { + background-color: #e6f7ff; + border-color: #1890ff; + color: #1890ff; + } +} +.group-expand-icon { + display: flex; + align-items: center; + justify-content: center; + width: 16px; + height: 16px; + cursor: pointer; + border-radius: 2px; + transition: all 0.2s ease; + margin-right: 4px; + color: #333; +} +.group-expand-icon .svg-icon { + transition: transform 0.2s ease; +} +.group-layer .layer-type-icon { + font-size: 14px; +} +.child-layers { + position: relative; +} +.child-layers::before { + content: ''; + position: absolute; + left: 8px; + top: 0; + bottom: 0; + width: 1px; + background-color: #e0e0e0; +} +.layer-indent { + width: 16px; + position: relative; +} +.layer-indent::after { + content: ''; + position: absolute; + left: 8px; + top: 50%; + width: 8px; + height: 1px; + background-color: #e0e0e0; +} +.child-layers-expand-enter-active, +.child-layers-expand-leave-active { + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + overflow: hidden; +} +.child-layers-expand-enter-from { + height: 0; + opacity: 0; + padding-top: 0; + padding-bottom: 0; + margin-top: 0; + margin-bottom: 0; +} +.child-layers-expand-leave-to { + height: 0; + opacity: 0; + padding-top: 0; + padding-bottom: 0; + margin-top: 0; + margin-bottom: 0; +} +.group-expand-icon { + display: flex; + align-items: center; + justify-content: center; + width: 16px; + height: 16px; + cursor: pointer; + border-radius: 2px; + transition: all 0.2s ease; + margin-right: 4px; +} +.group-expand-icon:hover { + background-color: rgba(0, 0, 0, 0.1); + transform: scale(1.1); +} +.group-expand-icon:active { + transform: scale(0.95); +} +.group-expand-icon .svg-icon { + transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1); +} +.child-layers { + position: relative; + background: linear-gradient(135deg, rgba(240, 248, 255, 0.1) 0%, rgba(240, 248, 255, 0.05) 100%); +} +.child-layers::before { + content: ''; + position: absolute; + left: 8px; + top: 0; + bottom: 0; + width: 1px; + background: linear-gradient(to bottom, #e0e0e0 0%, rgba(224, 224, 224, 0.3) 100%); +} +.child-layers .layer-item { + animation: slideInRight 0.2s ease-out; + animation-fill-mode: both; +} +.child-layers .layer-item:nth-child(1) { + animation-delay: 0.05s; +} +.child-layers .layer-item:nth-child(2) { + animation-delay: 0.1s; +} +.child-layers .layer-item:nth-child(3) { + animation-delay: 0.15s; +} +.child-layers .layer-item:nth-child(4) { + animation-delay: 0.2s; +} +.child-layers .layer-item:nth-child(5) { + animation-delay: 0.25s; +} +@keyframes slideInRight { + from { + opacity: 0; + transform: translateX(-10px); + } + to { + opacity: 1; + transform: translateX(0); + } +} +@media (hover: none) and (pointer: coarse) { + .child-layers-expand-enter-active, + .child-layers-expand-leave-active { + transition: all 0.25s ease; + } + .group-expand-icon:hover { + transform: none; + background-color: transparent; + } + .group-expand-icon:active { + transform: scale(0.9); + background-color: rgba(0, 0, 0, 0.1); + } + .child-layers .layer-item { + animation-duration: 0.15s; + } +} diff --git a/src/component/Canvas/CanvasEditor/fabric-canvas-events.md b/src/component/Canvas/CanvasEditor/fabric-canvas-events.md new file mode 100644 index 00000000..0ea45747 --- /dev/null +++ b/src/component/Canvas/CanvasEditor/fabric-canvas-events.md @@ -0,0 +1,31 @@ +### 鼠标事件 + +- `mouse:down`:鼠标按下时触发 +- `mouse:up`:鼠标释放时触发 +- `mouse:move`:鼠标移动时触发 +- `mouse:over`:鼠标移入画布时触发 +- `mouse:out`:鼠标移出画布时触发 + +### 对象交互事件 + +- `object:selected`:对象被选中时触发 +- `object:modified`:对象属性(如位置、大小)修改后触发 +- `object:rotating`:对象旋转过程中触发 +- `object:scaling`:对象缩放过程中触发 +- `object:skewing`:对象倾斜过程中触发 + +### 画布操作事件 + +- `before:render`:画布即将重绘前触发 +- `after:render`:画布重绘完成后触发 +- `selection:created`:选中对象集合创建时触发 +- `selection:updated`:选中对象集合更新时触发 +- `selection:cleared`:选中对象集合清除时触发 + +### 其他事件 + +- `object:added`:对象添加到画布时触发 +- `object:removed`:对象从画布移除时触发 +- `object:rotated`:对象旋转完成时触发 +- `object:scaled`:对象缩放完成时触发 +- `object:skewed`:对象倾斜完成时触发 \ No newline at end of file diff --git a/src/component/Canvas/CanvasEditor/index.vue b/src/component/Canvas/CanvasEditor/index.vue index f72cee5a..eecafc6f 100644 --- a/src/component/Canvas/CanvasEditor/index.vue +++ b/src/component/Canvas/CanvasEditor/index.vue @@ -20,8 +20,11 @@ import { SelectionManager } from "./managers/selection/SelectionManager"; 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 cuowuImg from "@/assets/images/homePage/cuowu.svg"; +import { Https } from "@/tool/https"; +import SelectImages from "@/component/common/SelectImages.vue"; +import CropImage from "./components/CropImage.vue"; +import { UrlToFile } from "@/tool/util"; // import { MinimapManager } from "./managers/minimap/MinimapManager"; @@ -32,6 +35,7 @@ import LayersPanel from "./components/LayersPanel/LayersPanel.vue"; import BrushControlPanel from "./components/BrushControlPanel.vue"; import TextEditorPanel from "./components/TextEditorPanel.vue"; // 引入文本编辑面板 import LiquifyPanel from "./components/LiquifyPanel.vue"; // 引入液化编辑面板 +import SelectMenuPanel from "./components/SelectMenuPanel.vue"; // 引入选择工具菜单组件 import SelectionPanel from "./components/SelectionPanel.vue"; // 引入选区面板 import { LayerType, OperationType } from "./utils/layerHelper.js"; import { ToolManager } from "./managers/ToolManager.js"; @@ -52,6 +56,7 @@ const emit = defineEmits([ "trigger-red-green-mouseup", // 红绿图模式鼠标抬起事件 "changeCanvas", // 画布变更事件 "canvasInit", // 画布初始化事件 + "trigger-library", // 触发打开Library选择图片事件 ]); const props = defineProps({ @@ -96,11 +101,28 @@ const props = defineProps({ type: Boolean, default: false, // 是否允许擦除背景图层 }, - + isBackgroundChangeable: { + type: Boolean, + default: true, // 是否允许修改背景图层 + }, showFixedLayer: { type: Boolean, default: false, // 是否显示固定图层 }, + isGeneral: { + // 从generalMiniCanvas来的 + type: Boolean, + default: false, + }, + isEdit: { + // 从design点击喜欢过的图片,再点击顶部的编辑图标 + type: Boolean, + default: false, + }, + hideCanvas: { + type: Boolean, + default: false, // 是否隐藏画布-隐藏关闭部分功能 + }, }); // 引用和状态 @@ -108,6 +130,7 @@ const canvasRef = ref(null); const canvasContainerRef = shallowRef(null); const imageUploadRef = ref(null); const currentZoom = ref(100); +const appContainerRef = ref(null); // 画布设置 const canvasWidth = ref(props.config.width); @@ -158,6 +181,15 @@ function toggleShortcutHelp() { showShortcutHelp.value = !showShortcutHelp.value; } +watch(()=>props.hideCanvas, (newVal)=>{ + console.log("==========是否隐藏画布",newVal) + if(newVal){ + keyboardManager?.removeEvents() + }else { + keyboardManager?.init() + } +}) + // 工具选择处理 function handleToolSelect(tool) { activeTool.value = tool; @@ -257,7 +289,7 @@ onMounted(async () => { layerManager, activeTool, // 响应式引用,存储当前选中的工具 brushSize: brushSize.value, // 可选,初始画笔大小 - t, // 国际化函数 + t, // 国际化函数 }); // 初始化文本编辑功能 @@ -276,6 +308,20 @@ onMounted(async () => { commandManager, layerManager, toolManager, + isRedGreenMode, + pasteText: (text) => { + // console.log("粘贴的文本:", text); + handleAddText(text); + }, + pasteImage: (file) => { + // console.log("粘贴的图片:", file); + uploadImageAndCreateLayer({ + file, + layerManager, + toolManager, + canvas: canvasManager.canvas, + }); + }, }); // 绑定快捷键事件 @@ -404,10 +450,9 @@ onMounted(async () => { canvasManagerLoaded.value = true; - // 添加删除按钮 - // if(!fabric.Object.prototype.controls.deleteControl)addRemoveBtn(removeLayer) - addRemoveBtn(removeLayer) - + // 添加删除按钮 + // if(!fabric.Object.prototype.controls.deleteControl)addRemoveBtn(removeLayer) + addRemoveBtn(removeLayer); // 触发组件初始化事件 nextTick(() => { @@ -456,6 +501,15 @@ onMounted(async () => { // 使用window的resize事件代替ResizeObserver // 只有当窗口大小变化时才更新画布尺寸 // window.addEventListener("resize", handleWindowResize); + if (props.config.initZoom) { + const width = canvasManager.width; + const height = canvasManager.height; + const cwidth = props.config.width; + const cheight = props.config.height; + let zoom = Math.min(1, width / cwidth, height / cheight); + if (zoom < 1) zoom -= 0.05; + setZoom(zoom); // 设置画布缩放 + } }); watchEffect(() => { @@ -480,15 +534,15 @@ onBeforeUnmount(() => { // return; // 开发环境下不卸载组件 // } console.log("onBeforeUnmount 组件卸载,清理资源..."); - // canvasManager?.dispose?.(); - // commandManager?.dispose?.(); - // layerManager?.dispose?.(); - // keyboardManager?.dispose?.(); - // toolManager?.dispose?.(); - // liquifyManager?.dispose?.(); - // selectionManager?.dispose?.(); - // redGreenModeManager?.dispose?.(); - // minimapManager?.dispose?.(); + canvasManager?.dispose?.(); + commandManager?.dispose?.(); + layerManager?.dispose?.(); + keyboardManager?.dispose?.(); + toolManager?.dispose?.(); + liquifyManager?.dispose?.(); + selectionManager?.dispose?.(); + redGreenModeManager?.dispose?.(); +// minimapManager?.dispose?.(); canvasManager = null; commandManager = null; layerManager = null; @@ -497,7 +551,7 @@ onBeforeUnmount(() => { liquifyManager = null; selectionManager = null; redGreenModeManager = null; -// fabric.Object.prototype.controls.deleteControl = undefined; + // fabric.Object.prototype.controls.deleteControl = undefined; // 移除window resize事件监听 // window.removeEventListener("resize", handleWindowResize); @@ -520,6 +574,18 @@ function handleWindowResize() { function resetZoom() { canvasManager.resetZoom(); } +function setZoom(zoom) { + setTimeout(() => { + if (!canvasManager) return; + const newZoom = Math.max(zoom, 0.1); + // 使用画布中心作为缩放点 + const centerPoint = { + x: canvasManager.canvas.width / 2, + y: canvasManager.canvas.height / 2, + }; + canvasManager.animateZoom(centerPoint, newZoom); + }); +} function zoomIn() { if (!canvasManager) return; @@ -547,7 +613,6 @@ function zoomOut() { x: canvasManager.canvas.width / 2, y: canvasManager.canvas.height / 2, }; - canvasManager.animateZoom(centerPoint, newZoom); } @@ -574,12 +639,22 @@ function updateCanvasSize() { function updateCanvasColor() { canvasManager.setCanvasColor(canvasColor.value); } - +function createLayerName(){ + const layer = t("Canvas.layer") + // 检查图层名称是否已存在 + let layerIndex = 1; + let layerName = `${layer + " " + layerIndex}`; + while (layerManager.getLayerByName(layerName)) { + layerIndex++; + layerName = `${layer} ${layerIndex}`; + } + return layerName; +} async function addLayer() { - await layerManager.createLayer(t("Canvas.EmptyLayer")); + await layerManager.createLayer(createLayerName()); } async function addTopLayer() { - await layerManager.createLayer("空图层", LayerType.EMPTY, { + await layerManager.createLayer(createLayerName(), LayerType.EMPTY, { insertTop: true, }); } @@ -612,65 +687,75 @@ function moveLayerDown(layerId) { layerManager.moveLayer(layerId, "down"); } -function addRemoveBtn(fun){//添加删除按钮 - const deleteIcon = cuowuImg - // 创建删除图片元素 - let deleteImg = document.createElement('img') - deleteImg.src = deleteIcon - function renderIcon(icon) { - return function (ctx, left, top, styleOverride, fabricObject) { - var size = this.cornerSize; - ctx.save(); - ctx.translate(left, top); - ctx.rotate(fabric.util.degreesToRadians(fabricObject.angle)); - ctx.drawImage(icon, -size/3, -size/3, size/1.5, size/1.5); - ctx.restore(); - } - } - fabric.Object.prototype.controls.deleteControl = new fabric.Control({ - x: 0.5, - y: -0.5, - offsetY: -16, - offsetX: 16, - cursorStyle: 'pointer', - mouseUpHandler:deleteFun, - render: renderIcon(deleteImg), - cornerSize: 24 - }) +function addRemoveBtn(fun) { + //添加删除按钮 + const deleteIcon = cuowuImg; + // 创建删除图片元素 + let deleteImg = document.createElement("img"); + deleteImg.src = deleteIcon; + function renderIcon(icon) { + return function (ctx, left, top, styleOverride, fabricObject) { + var size = this.cornerSize; + ctx.save(); + ctx.translate(left, top); + ctx.rotate(fabric.util.degreesToRadians(fabricObject.angle)); + ctx.drawImage(icon, -size / 3, -size / 3, size / 1.5, size / 1.5); + ctx.restore(); + }; + } + fabric.Object.prototype.controls.deleteControl = new fabric.Control({ + x: 0.5, + y: -0.5, + offsetY: -16, + offsetX: 16, + cursorStyle: "pointer", + mouseUpHandler: deleteFun, + render: renderIcon(deleteImg), + cornerSize: 24, + }); } -function deleteFun(){ - removeLayer(layerManager.activeLayerId.value) +function deleteFun() { + removeLayer(layerManager.activeLayerId.value); } 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); - if (layerToRemove) { - const elementIds = layerToRemove?.fabricObjects?.map((e) => e.id); - elementIds.forEach((elementId) => { - const objectToRemove = canvasManager.canvas - .getObjects() - .find((obj) => obj.id === elementId); - if (objectToRemove) { - canvasManager.canvas.remove(objectToRemove); - } - }); - if (activeLayerId.value === layerId) { - activeElementId.value = null; - } - canvasManager.canvas.renderAll(); - } - } - layerManager.removeLayer(layerId); + layerManager.removeLayer(layerId); +// 此处删除画布上内容导致撤回操作无效(多余) +// if (canvasManager && canvasManager.canvas) { +// const layerToRemove = layers.value.find((l) => l.id === layerId); +// if (layerToRemove) { +// const elementIds = layerToRemove?.fabricObjects?.map((e) => e.id); +// elementIds.forEach((elementId) => { +// const objectToRemove = canvasManager.canvas +// .getObjects() +// .find((obj) => obj.id === elementId); +// if (objectToRemove) { +// canvasManager.canvas.remove(objectToRemove); +// } +// }); +// if (activeLayerId.value === layerId) { +// activeElementId.value = null; +// } +// canvasManager.canvas.renderAll(); +// } +// } } function triggerImageUpload() { @@ -705,11 +790,26 @@ function handleImageUpload(event) { }); } -function handleAddText() { +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(text) { if (toolManager && canvasManager && canvasManager.canvas) { // 在画布中央创建文本 const canvasCenter = canvasManager.canvas.getCenter(); - toolManager.createText(canvasCenter.left, canvasCenter.top); + toolManager.createText(canvasCenter.left, canvasCenter.top, text); } } @@ -802,13 +902,49 @@ const changeCanvas = async (command) => { ...command, // 传递完整的命令数据 }; emit("changeCanvas", commandData); - if(command.canUndo || command.canRedo){ - setTimeout(async ()=>{ - const imageData = await canvasManager.exportImage({ - restoreOpacityInRedGreen: true, // 恢复红绿图模式下的透明度 - }); - emit("trigger-red-green-mouseup", imageData); - },100) + if (command.canUndo || command.canRedo) { + setTimeout(async () => { + const imageData = await canvasManager.exportImage({ + restoreOpacityInRedGreen: true, // 恢复红绿图模式下的透明度 + isCropByBg: true, + }); + emit("trigger-red-green-mouseup", imageData); + }, 100); + } +}; + +const cropImageRef = ref(null); +const cropImage = (url) => { + return cropImageRef.value.open(url) +}; +provide("cropImage", cropImage); // 提供给子组件使用 + +// 处理画布容器的拖放事件 +const isDragOver = ref(false); +const canvasDragover = (e) => { + e.preventDefault(); + if (isRedGreenMode.value) return; + const types = e.dataTransfer.types; + isDragOver.value = types.includes("Files"); +}; + +// 处理画布容器的拖离事件 +const canvasDragleave = (e) => { + e.preventDefault(); + if (isRedGreenMode.value) return; + isDragOver.value = false; +}; + +// 处理画布容器的拖放事件 +const canvasDragdrop = (e) => { + e.preventDefault(); + if (isRedGreenMode.value) return; + isDragOver.value = false; + const files = e.dataTransfer.files; + for (const file of files) { + if (file.type.startsWith("image/")) { + handleImageUpload({ target: { files: [file] } }); + } } }; @@ -882,6 +1018,7 @@ defineExpose({ layerId = "", // 导出具体图层ID layerIdArray = [], // 导出多个图层ID数组 expPicType = "png", // 导出图片类型 JPG 或 PNG ,SVG + isEnhanceImg, // 是否是增强图片 } = {}) => { return canvasManager.exportImage({ isContainBg, @@ -890,6 +1027,7 @@ defineExpose({ layerId, layerIdArray, expPicType, + isEnhanceImg, }); }, /** @@ -1000,7 +1138,13 @@ defineExpose({
diff --git a/src/component/Detail/DesignDetail.vue b/src/component/Detail/DesignDetail.vue index 7f480dd0..d887d1a2 100644 --- a/src/component/Detail/DesignDetail.vue +++ b/src/component/Detail/DesignDetail.vue @@ -39,6 +39,10 @@
{{$t('DesignPrintOperation.Elements')}}
+
- +
@@ -57,18 +61,21 @@
-
+
@@ -77,6 +84,7 @@ v-show=" currentDetailType !== 'color' && (currentDetailType === 'element' || + currentDetailType === 'accessory' || currentDetailType === 'print' || (currentDetailType === 'sketch' && selectDetail?.newDetail?.[currentDetailType])|| (currentDetailType === 'sketch' && selectDetail?.sketchString)|| @@ -130,6 +138,7 @@ export default defineComponent({ model:null, canvasBox, detailRight, + detailLeft:null as any, }) const userDetail = computed(()=>{ return store.state.UserHabit.userDetail @@ -154,8 +163,10 @@ export default defineComponent({ fun:null, }, positionKey:0, + isUndividedLayerWithSinglePrint:false, }) + provide('getCanvasIfEdit',detailData.getCanvasIfEdit) provide('singleOveral',detailData.singleOveral) provide('isEditPattern',detailData.isEditPattern) @@ -167,60 +178,73 @@ export default defineComponent({ } const showDesignDetailModal = (data:any,str:any)=>{ - // let url = Https.httpUrls.getDesignDetail + `?designItemId=${77770}&designPythonOutfitId=${77423}` - let url = Https.httpUrls.getDesignDetail + `?designItemId=${data.design.designItemId}&designPythonOutfitId=${data.design.designOutfitId}` - detailData.loadingShow = true - Https.axiosGet(url).then( - async (rv: any) => { - store.commit('DesignDetail/setDesignDetail',rv) - rv.clothes.forEach((item:any)=>{ - let a - item.designType='Library' - if(item.layersObject[0].imageCategory.indexOf("back") == -1){ - a = item.layersObject[0] - item.layersObject[0] = item.layersObject[1] - item.layersObject[1] = a - } - if(item.color){ - item.color.rgba = { - r:item.color.r, - g:item.color.g, - b:item.color.b, + return new Promise((resolve, reject) => { + store.commit('DesignDetail/clearDetailData') + // let url = Https.httpUrls.getDesignDetail + `?designItemId=${77770}&designPythonOutfitId=${77423}` + let url = Https.httpUrls.getDesignDetail + `?designItemId=${data.design.designItemId}&designPythonOutfitId=${data.design.designOutfitId}` + detailData.loadingShow = true + Https.axiosGet(url).then( + async (rv: any) => { + store.commit('DesignDetail/setDesignDetail',rv) + rv.clothes.forEach((item:any)=>{ + let a + item.designType='Library' + if(item.layersObject[0].imageCategory.indexOf("back") == -1){ + a = item.layersObject[0] + item.layersObject[0] = item.layersObject[1] + item.layersObject[1] = a } - }else{ - item.color = { - // rgba:{ - // r:undefined, - // g:undefined, - // b:undefined, - // } + if(item.color){ + item.color.rgba = { + r:item.color.r, + g:item.color.g, + b:item.color.b, + } + }else{ + item.color = { + // rgba:{ + // r:undefined, + // g:undefined, + // b:undefined, + // } + } } - } - if(item.gradient){ - item.color.gradient = item.gradient - } - if(item.printObject.prints == null)item.printObject.prints = [] - item.printObject.prints.forEach((element:any) => { - if(!element.designType){ - element.designType = 'Library' + if(item.gradient){ + item.color.gradient = item.gradient } - }); - }) - detailData.singleOveral.value = rv.singleOverall - detailData.designDetailShow = true - // this.deleteShow = false - initialize() - setRevocation() - detailData.loadingShow = false - if(rv.singleOverall == "single"){ - store.commit('DesignDetail/setDesignColthes',rv.clothes[0].id) - } + if(item.printObject.prints == null)item.printObject.prints = [] + item.printObject.prints.forEach((element:any) => { + if(!element.designType){ + element.designType = 'Library' + } + }); + if(!item.layersObject[0].undividedLayerWithSinglePrint){ + detailData.isUndividedLayerWithSinglePrint = true + } + }) + detailData.singleOveral.value = rv.singleOverall + detailData.designDetailShow = true + // this.deleteShow = false + initialize() + setRevocation() + if(rv.singleOverall == "single"){ + store.commit('DesignDetail/setDesignColthes',rv.clothes[0].id) + modelOnLoad() + } - } - - ).catch(rv=>{ - detailData.loadingShow = false - }) + + if(detailData.isUndividedLayerWithSinglePrint){ + }else{ + detailData.loadingShow = false + } + resolve(rv) + } + ).catch(rv=>{ + detailData.loadingShow = false + resolve(rv) + }) + }) + } const initialize = ()=>{//design后初始化 @@ -232,15 +256,13 @@ export default defineComponent({ const setRevocation = ()=>{//设置撤销 let itemDetail = JSON.parse(JSON.stringify(detailData.designDetail)) let revocation:any = JSON.parse((sessionStorage.getItem("revocation") as any)) + if(!revocation)revocation = [] // let oppositeRevocation = JSON.parse((sessionStorage.getItem("oppositeRevocation") as any)) - if(revocation?.[0]?.designItemId != itemDetail.designItemId || revocation?.[0]?.designItemId == undefined){ - // sessionStorage.setItem('revocation', JSON.stringify([])); - // sessionStorage.setItem('oppositeRevocation',JSON.stringify([])); - revocation = [] - } - revocation.push(itemDetail) + // if(revocation?.[0]?.designItemId != itemDetail.designItemId || revocation?.[0]?.designItemId == undefined){ + // revocation = [] + // } + revocation.push({designData:itemDetail,position:null}) detailData.revocationShow = revocation?.length - detailData.oppositeRevocationShow = 0 sessionStorage.setItem('revocation', JSON.stringify(revocation)); sessionStorage.setItem('oppositeRevocation',JSON.stringify([])); } @@ -249,13 +271,16 @@ export default defineComponent({ const revocation = ()=>{//撤回 let oppositeRevocation = JSON.parse((sessionStorage.getItem("oppositeRevocation") as any)) let revocation = JSON.parse((sessionStorage.getItem("revocation") as any)) - if(detailData.revocationShow <= 1)return + if(revocation.length <= 1)return oppositeRevocation.push(revocation[revocation.length-1]) - detailData.oppositeRevocationShow = oppositeRevocation.length revocation.splice(revocation.length-1,1) detailData.revocationShow = revocation.length // store.commit("DesignDetail/setDesignDetail", revocation[revocation.length-1]); - store.commit('DesignDetail/setDesignDetail',revocation[revocation.length-1]) + if(revocation[revocation.length-1].designData){ + store.commit('DesignDetail/setDesignDetail',revocation[revocation.length-1].designData) + }else{ + store.commit('DesignDetail/setFrontBack',revocation[revocation.length-1].position) + } store.commit('DesignDetail/setDesignColthes',detailData.selectDetail.id) sessionStorage.setItem('oppositeRevocation', JSON.stringify(oppositeRevocation)); sessionStorage.setItem('revocation', JSON.stringify(revocation)); @@ -265,8 +290,13 @@ export default defineComponent({ const oppositeRevocation = ()=>{//反撤回 let oppositeRevocation = JSON.parse((sessionStorage.getItem("oppositeRevocation") as any)) let revocation = JSON.parse((sessionStorage.getItem("revocation") as any)) - if(!oppositeRevocation[oppositeRevocation.length-1])return - store.commit("DesignDetail/setDesignDetail", oppositeRevocation[oppositeRevocation.length-1]); + // if(!oppositeRevocation[oppositeRevocation.length-1].designData)return + if(oppositeRevocation.length < 1)return + if(oppositeRevocation[oppositeRevocation.length-1]?.designData){ + store.commit('DesignDetail/setDesignDetail',oppositeRevocation[oppositeRevocation.length-1].designData) + }else if(oppositeRevocation[oppositeRevocation.length-1]?.position){ + store.commit('DesignDetail/setFrontBack',oppositeRevocation[oppositeRevocation.length-1].position) + } store.commit('DesignDetail/setDesignColthes',detailData.selectDetail.id) revocation.push(oppositeRevocation[oppositeRevocation.length-1]) detailData.revocationShow = revocation.length @@ -282,9 +312,10 @@ export default defineComponent({ } const setClothes = async (list:any)=>{ let clothesList:any = [] + await nextTick() for(let i = 0;i{ // return let workspace = store.state.Workspace.probjects - if(!detailData.selectDetail.path && !detailData.selectDetail.newDetail?.sketch?.minIOPath)return + if(!detailData?.selectDetail?.path && !detailData?.selectDetail?.newDetail?.sketch?.minIOPath)return let clothes:any - if(detailData.currentDetailType == 'models'){ + if(detailData.currentDetailType == 'models' || detailData.isUndividedLayerWithSinglePrint){ clothes = await setClothes(detailData.designDetail.clothes) }else{ clothes = await setClothes([detailData.selectDetail]) @@ -352,9 +389,9 @@ export default defineComponent({ let data = { designItemId:detailData.designDetail.designItemId, designSingleItemDTOList:clothes, - isPreview:true, + isPreview:str == 'sub'?false: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:'', @@ -369,10 +406,12 @@ export default defineComponent({ rv:rv, fun:setRevocation } - detailData.designDetail.oldModel = detailData.designDetail.newModel + if(detailData?.designDetail?.newModel)detailData.designDetail.oldModel = JSON.parse(JSON.stringify(detailData.designDetail.newModel)) delete detailData.designDetail.newModel store.commit('DesignDetail/setPraeview',value) detailData.loadingShow = false + detailData.isUndividedLayerWithSinglePrint = false + canvasReload() // setRevocation() }).catch(res=>{ detailData.loadingShow = false @@ -386,7 +425,7 @@ export default defineComponent({ designSingleItemDTOList:clothes, isPreview:false, // 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:'', @@ -421,6 +460,13 @@ export default defineComponent({ let data = getSubmitData('preview') store.dispatch('DesignDetail/setSubmit',data) } + const modelOnLoad = ()=>{ + if(!detailData.isUndividedLayerWithSinglePrint)return + setTimeout(()=>{ + let data = getSubmitData('sub') + store.dispatch('DesignDetail/setSubmit',data) + }) + } const detailEdit = async (str:any)=>{ if(str){ if(detailData.isEditPattern.value && detailData.isEditPattern.value == str){ @@ -449,6 +495,17 @@ export default defineComponent({ store.commit('DesignDetail/setDesignDetail',detailData.designDetail) },1000) } + const sketchSysToLibrary = ()=>{//系统sketch添加到library更新library + coverRevocation() + detailDom.detailLeft.sketchSysToLibrary() + } + const coverRevocation = ()=>{ + let itemDetail = JSON.parse(JSON.stringify(detailData.designDetail)) + let revocation = JSON.parse((sessionStorage.getItem("revocation") as any)) + revocation.splice(revocation.length-1,1,{designData:itemDetail,position:null}) + sessionStorage.setItem('revocation', JSON.stringify(revocation)); + sessionStorage.setItem('oppositeRevocation',JSON.stringify([])); + } onMounted(()=>{ window.addEventListener('resize', handleResize); }) @@ -472,6 +529,8 @@ export default defineComponent({ oppositeRevocation, detailEdit, canvasReload, + modelOnLoad, + sketchSysToLibrary, } }, @@ -520,7 +579,7 @@ export default defineComponent({ \ No newline at end of file diff --git a/src/component/Detail/detailLeft/colorBox/index.vue b/src/component/Detail/detailLeft/colorBox/index.vue index 3d060543..6607ff37 100644 --- a/src/component/Detail/detailLeft/colorBox/index.vue +++ b/src/component/Detail/detailLeft/colorBox/index.vue @@ -16,8 +16,16 @@
{{$t('DesignPrintOperation.Colorfromimage')}}
-
- +
+
+ +
{{ $t('LibraryPage.Upload') }}
+
+
+ + +
{{ $t('LibraryPage.library') }}
+
{{$t('DesignPrintOperation.ColorCode')}}
@@ -30,7 +38,14 @@
- + \ No newline at end of file diff --git a/src/component/Detail/detailLeft/module/currentList.vue b/src/component/Detail/detailLeft/module/currentList.vue index 95143250..90163850 100644 --- a/src/component/Detail/detailLeft/module/currentList.vue +++ b/src/component/Detail/detailLeft/module/currentList.vue @@ -5,7 +5,7 @@
- +
@@ -48,13 +48,17 @@ export default defineComponent({ color:computed(()=>store.state.UploadFilesModule.allBoardData.colorBoards), models:computed(()=>store.state.Workspace.probjects.model), }, + sketchCatecoryAllList:computed(()=>{ + return store.state.Workspace.workspaceAllPosition + }), currentDetailType:computed(()=>store.state.DesignDetail.currentDetailType), }) const getDetailListData = reactive({ }) - const selectImgItem = (file:any)=>{ + const selectImgItem = (data:any)=>{ + let file = JSON.parse(JSON.stringify(data)) if(props.type != 'models'){ if(!file.resData?.minIOPath){ file.minIOPath = getMinioUrl(file?.imgUrl || file?.resData?.url) diff --git a/src/component/Detail/detailLeft/module/libraryList.vue b/src/component/Detail/detailLeft/module/libraryList.vue index 284999c8..bd999c07 100644 --- a/src/component/Detail/detailLeft/module/libraryList.vue +++ b/src/component/Detail/detailLeft/module/libraryList.vue @@ -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,7 +350,8 @@ export default defineComponent({ margin-top: 1rem; justify-content: space-between; align-content: flex-start; - &::-webkit-scrollbar{display: none;} + padding-bottom: 2rem; + // &::-webkit-scrollbar{display: none;} > .content_img_item{ width: calc((50% - 1rem)); > .content_img_item_block{ @@ -365,9 +369,12 @@ export default defineComponent({ > .material_content_list_loding{ width: 100%; aspect-ratio: 1/1; + height: 4rem; overflow: hidden; > img{ width: 100%; + height: 100%; + object-fit: contain; } } } diff --git a/src/component/Detail/detailLeft/module/selectList.vue b/src/component/Detail/detailLeft/module/selectList.vue index 0729390d..489df33f 100644 --- a/src/component/Detail/detailLeft/module/selectList.vue +++ b/src/component/Detail/detailLeft/module/selectList.vue @@ -179,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; diff --git a/src/component/Detail/detailLeft/module/uploadList.vue b/src/component/Detail/detailLeft/module/uploadList.vue index 851ae3af..b11e8bae 100644 --- a/src/component/Detail/detailLeft/module/uploadList.vue +++ b/src/component/Detail/detailLeft/module/uploadList.vue @@ -129,6 +129,7 @@ export default defineComponent({ file.designType = res.data.designType file.level2Type = type; + file.resData.level2Type = type; file.minIOPath = file.resData.minIOPath let fileList = detailData.uploadList.filter( (v:any) => v.status === "done" diff --git a/src/component/Detail/detailLeft/sketch.vue b/src/component/Detail/detailLeft/sketch.vue index a637ca17..76a7bdf4 100644 --- a/src/component/Detail/detailLeft/sketch.vue +++ b/src/component/Detail/detailLeft/sketch.vue @@ -12,7 +12,7 @@
- + diff --git a/src/component/HomePage/MarketingSketchUpload.vue b/src/component/HomePage/MarketingSketchUpload.vue index 399bf660..40fbea49 100644 --- a/src/component/HomePage/MarketingSketchUpload.vue +++ b/src/component/HomePage/MarketingSketchUpload.vue @@ -214,7 +214,7 @@ export default defineComponent({ display: inline-block; width: 16.5rem; height: 16.5rem; - border: 1px solid #F5F5F5; + border: 1px solid #F9FAFA; vertical-align: top; &.upload_component{ diff --git a/src/component/HomePage/Material.vue b/src/component/HomePage/Material.vue index 148c482b..6d4280f7 100644 --- a/src/component/HomePage/Material.vue +++ b/src/component/HomePage/Material.vue @@ -597,7 +597,7 @@ export default defineComponent({ // height: calc(10rem); width: calc(25% - 2rem); aspect-ratio: 1 / 1; - border: 1px solid #f5f5f5; + border: 1px solid #F9FAFA; position: relative; cursor: pointer; padding: 0; diff --git a/src/component/HomePage/NewCollectionReview.vue b/src/component/HomePage/NewCollectionReview.vue index 2b717b6d..9f447ac9 100644 --- a/src/component/HomePage/NewCollectionReview.vue +++ b/src/component/HomePage/NewCollectionReview.vue @@ -136,7 +136,7 @@ export default defineComponent({ data(){ return{ imgOpen:true, - + setSketchTime:null as any, } }, watch: { @@ -153,12 +153,18 @@ export default defineComponent({ newArr.push(newVal?.[index]?.id?newVal?.[index]?.id:newVal?.[index]?.sketchBoardIdd) }); if(JSON.stringify(newArr)!=JSON.stringify(oldArr)){ - this.setSketch() + clearTimeout(this.setSketchTime) + this.setSketchTime = setTimeout(()=>{ + this.setSketch() + },500) this.imgOpen = true } }else{ nextTick(()=>{ - this.setSketch() + clearTimeout(this.setSketchTime) + this.setSketchTime = setTimeout(()=>{ + this.setSketch() + },500) this.imgOpen = true }) } @@ -201,6 +207,7 @@ export default defineComponent({ let sketchH = [0,0,0] nextTick().then(async ()=>{ if(this.sketchList && this.sketchList!=null){ + console.log(JSON.parse(JSON.stringify(this.sketch)),JSON.parse(JSON.stringify(this.sketchList))) for (let i = 0; i < this.sketchList?.length; i++) { let sketch1:any = document.getElementsByClassName('collection_review')[0]?.getElementsByClassName('lager_img_item0')[0]?.getBoundingClientRect() let sketch2:any = document.getElementsByClassName('collection_review')[0]?.getElementsByClassName('lager_img_item1')[0]?.getBoundingClientRect() @@ -232,6 +239,7 @@ export default defineComponent({ } }) } + console.log(JSON.parse(JSON.stringify(this.sketch))) this.imgOpen = true this.store.commit('setshowSketchList', this.sketch) } diff --git a/src/component/HomePage/UpgradePlan.vue b/src/component/HomePage/UpgradePlan.vue index 952984a0..75e9ec37 100644 --- a/src/component/HomePage/UpgradePlan.vue +++ b/src/component/HomePage/UpgradePlan.vue @@ -116,7 +116,7 @@ import { Https } from "@/tool/https"; import { useStore } from "vuex"; import { useI18n } from "vue-i18n"; import payMethod from "@/component/Pay/payMethod.vue"; -import { compute } from "three/tsl"; +// import { compute } from "three/tsl"; // import { forEach } from "jszip"; export default defineComponent({ components: { diff --git a/src/component/HomePage/bindEmail.vue b/src/component/HomePage/bindEmail.vue index 872278b0..d4b18e4d 100644 --- a/src/component/HomePage/bindEmail.vue +++ b/src/component/HomePage/bindEmail.vue @@ -365,6 +365,7 @@ export default defineComponent({ title:this.selectSex, surname:this.surname, givenName:this.givenName, + userId:this.userDetail?.userId, }; if(this.loginTime){ this.loginTime = false @@ -421,6 +422,8 @@ export default defineComponent({ }, //创建定时器 createTimer() { + clearInterval(this.timer); + this.time = 60; this.timer = setInterval(() => { this.time--; if (!this.time) { @@ -639,7 +642,7 @@ export default defineComponent({ transition: all .3s; &.active{ color: #b8b8b8; - background: #f5f5f5; + background: #F9FAFA; } &:hover{ border: 0.1rem solid #000; diff --git a/src/component/HomePage/collectionModal.vue b/src/component/HomePage/collectionModal.vue index 1da86b34..e85da19b 100644 --- a/src/component/HomePage/collectionModal.vue +++ b/src/component/HomePage/collectionModal.vue @@ -468,6 +468,7 @@ export default defineComponent({ cursor: pointer; display: flex; height: 100%; + font-size: 1.8rem; } .fi::before{ padding: 5px; diff --git a/src/component/HomePage/generalMenu.vue b/src/component/HomePage/generalMenu.vue index 61c26a43..eda6986f 100644 --- a/src/component/HomePage/generalMenu.vue +++ b/src/component/HomePage/generalMenu.vue @@ -213,7 +213,6 @@ import { message, Upload, Modal } from "ant-design-vue"; onMounted(() => { instance.appContext.config.globalProperties.$dropdownEvents.onClose(removePrintModel) window.addEventListener('scroll', handleScroll, true) - console.log(instance,) }) onUnmounted(() => { diff --git a/src/component/HomePage/productImg.vue b/src/component/HomePage/productImg.vue deleted file mode 100644 index 232b43b3..00000000 --- a/src/component/HomePage/productImg.vue +++ /dev/null @@ -1,1145 +0,0 @@ - - - - - \ No newline at end of file diff --git a/src/component/HomePage/renew.vue b/src/component/HomePage/renew.vue index de626e08..9d48c5a0 100644 --- a/src/component/HomePage/renew.vue +++ b/src/component/HomePage/renew.vue @@ -1,961 +1,956 @@ - - - + + \ No newline at end of file diff --git a/src/component/HomePage/scaleImage.vue b/src/component/HomePage/scaleImage.vue index fcaf89a2..2f037d49 100644 --- a/src/component/HomePage/scaleImage.vue +++ b/src/component/HomePage/scaleImage.vue @@ -296,6 +296,8 @@ export default defineComponent({ elementId:scaleImageList.value[scaleImageIndex.value].elementId, elementType:scaleImageList.value[scaleImageIndex.value].elementType, } + obj.elementType = obj.elementType == 'Relight'?'ToProductImage':obj.elementType + // let imageStrength = productimg.productimgSimilarity == 100? 95 :productimg.productimgSimilarity let imageStrength = 70 / 100 * productimg.productimgSimilarity let data:any ={ @@ -608,30 +610,31 @@ export default defineComponent({ setImageIndex(index:any){ if(this.isNext)return let this_ = this - if(this.imgType == 'Printboard' || this.imgType == 'Sketchboard'){ - this.isNext = true - new Promise((resolve,reject)=>{ - Modal.confirm({ - title: this.t('scaleImage.submitCanvas'), - icon: createVNode(ExclamationCircleOutlined), - okText: 'Yes', - cancelText: 'No', - mask:false, - centered:true, - onOk() { - this_.scaleImageIndex = index - this_.isNext = false - resolve('') - }, - onCancel(){ - this_.isNext = false - resolve('') - } - }); - }) - }else{ - this.scaleImageIndex = index - } + // if(this.imgType == 'Printboard' || this.imgType == 'Sketchboard'){ + // this.isNext = true + // new Promise((resolve,reject)=>{ + // Modal.confirm({ + // title: this.t('scaleImage.submitCanvas'), + // icon: createVNode(ExclamationCircleOutlined), + // okText: 'Yes', + // cancelText: 'No', + // mask:false, + // centered:true, + // onOk() { + // this_.scaleImageIndex = index + // this_.isNext = false + // resolve('') + // }, + // onCancel(){ + // this_.isNext = false + // resolve('') + // } + // }); + // }) + // }else{ + // this.scaleImageIndex = index + // } + this.scaleImageIndex = index }, LikeFile(item:any,str:string){ let parent:any = this.$parent @@ -738,7 +741,7 @@ export default defineComponent({ overflow: hidden; /* 溢出部分隐藏 */ text-overflow: ellipsis; /* 显示省略号 */ &:hover{ - background: #f5f5f5; + background: #F9FAFA; } &:first-child{ margin-right: 0; diff --git a/src/component/HomePage/scaleVideo.vue b/src/component/HomePage/scaleVideo.vue index 6370db03..27770df1 100644 --- a/src/component/HomePage/scaleVideo.vue +++ b/src/component/HomePage/scaleVideo.vue @@ -4,9 +4,9 @@
-