huangmp 1 год назад
Родитель
Сommit
b49134c073

+ 276 - 243
src/components/canvas-param-pic-preview/index.vue

@@ -16,235 +16,239 @@
       :model="dataForm"
       align="center"
       size="small">
-      <el-row>
-        <el-col :span="5">
-          <el-form-item>
-            <h2>正面四色层</h2>
-            <div v-if="mode === 'view'">
-              <el-image
-                style="width: 295px; height: 452px"
-                :src="dataForm.frontCanvasParamObj.printed.indexOf('https://') !== -1? dataForm.frontCanvasParamObj.printed : resourcesUrl + dataForm.frontCanvasParamObj.printed"
-                v-if="dataForm.frontCanvasParamObj && dataForm.frontCanvasParamObj.printed"/>
-            </div>
-            <el-upload v-else
-                       class="avatar-uploader"
-                       accept="image/jpg"
-                       :before-upload="(file, fileList)=>handleBeforeUpload(file, fileList,dataForm)"
-                       :action="$http.adornUrl('/admin/file/simpleUpload')"
-                       :headers="{Authorization: $cookie.get('Authorization_vp'),locale:lang}"
-                       :on-success="(res,file)=>{onUploadSuccess(dataForm.frontCanvasParamObj, 'printed',res,file)}"
-                       :show-file-list="false">
-              <el-image v-if="dataForm.frontCanvasParamObj && dataForm.frontCanvasParamObj.printed" style="width: 295px; height: 452px" :src="resourcesUrl + dataForm.frontCanvasParamObj.printed" class="avatar"/>
-            </el-upload>
-          </el-form-item>
-          <el-button v-if="mode==='edit' && dataForm.frontCanvasParamObj && dataForm.frontCanvasParamObj.printed" type="primary" size="mini" style="margin-right: 5px" @click="saveOrUpdateCanvasParam()">保存</el-button>
-        </el-col>
-        <el-col :span="5">
-          <el-form-item>
-            <h2>正面白墨层</h2>
-            <div v-if="mode === 'view'">
-              <el-image
-                style="width: 295px; height: 452px"
-                :src="dataForm.frontCanvasParamObj.whiteBoard.indexOf('https://') !== -1? dataForm.frontCanvasParamObj.whiteBoard : resourcesUrl + dataForm.frontCanvasParamObj.whiteBoard"
-                v-if="dataForm.frontCanvasParamObj && dataForm.frontCanvasParamObj.whiteBoard"/>
-            </div>
-            <el-upload v-else
-                       class="avatar-uploader"
-                       accept="image/jpg"
-                       :before-upload="(file, fileList)=>handleBeforeUpload(file, fileList,dataForm)"
-                       :action="$http.adornUrl('/admin/file/simpleUpload')"
-                       :headers="{Authorization: $cookie.get('Authorization_vp'),locale:lang}"
-                       :on-success="(res,file)=>{onUploadSuccess(dataForm.frontCanvasParamObj, 'whiteBoard',res,file)}"
-                       :show-file-list="false">
-              <el-image v-if="dataForm.frontCanvasParamObj && dataForm.frontCanvasParamObj.whiteBoard" style="width: 295px; height: 452px" :src="resourcesUrl + dataForm.frontCanvasParamObj.whiteBoard" class="avatar"/>
-            </el-upload>
-          </el-form-item>
-          <el-button v-if="mode==='edit' && dataForm.frontCanvasParamObj && dataForm.frontCanvasParamObj.whiteBoard" type="primary" size="mini" style="margin-right: 5px" @click="saveOrUpdateCanvasParam()">保存</el-button>
-        </el-col>
-        <el-col :span="5">
-          <el-form-item>
-            <h2>正面烫色层</h2>
-            <div v-if="mode === 'view'">
-              <el-image
-                style="width: 295px; height: 452px"
-                :src="dataForm.frontCanvasParamObj.foilstamping.indexOf('https://') !== -1? dataForm.frontCanvasParamObj.foilstamping : resourcesUrl + dataForm.frontCanvasParamObj.foilstamping"
-                v-if="dataForm.frontCanvasParamObj && dataForm.frontCanvasParamObj.foilstamping"/>
-            </div>
-            <el-upload v-else
-                       class="avatar-uploader"
-                       accept="image/jpg"
-                       :before-upload="(file, fileList)=>handleBeforeUpload(file, fileList,dataForm)"
-                       :action="$http.adornUrl('/admin/file/simpleUpload')"
-                       :headers="{Authorization: $cookie.get('Authorization_vp'),locale:lang}"
-                       :on-success="(res,file)=>{onUploadSuccess(dataForm.frontCanvasParamObj, 'foilstamping',res,file)}"
-                       :show-file-list="false">
-              <el-image v-if="dataForm.frontCanvasParamObj && dataForm.frontCanvasParamObj.foilstamping" style="width: 295px; height: 452px" :src="resourcesUrl + dataForm.frontCanvasParamObj.foilstamping" class="avatar"/>
-            </el-upload>
-          </el-form-item>
-          <el-button v-if="mode==='edit' && dataForm.frontCanvasParamObj && dataForm.frontCanvasParamObj.foilstamping" type="primary" size="mini" style="margin-right: 5px" @click="saveOrUpdateCanvasParam()">保存</el-button>
-        </el-col>
-        <el-col :span="5">
-          <el-form-item>
-            <h2>正面逆向层</h2>
-            <div v-if="mode === 'view'">
-              <el-image
-                style="width: 295px; height: 452px"
-                :src="dataForm.frontCanvasParamObj.unWhiteBoard.indexOf('https://') !== -1? dataForm.frontCanvasParamObj.unWhiteBoard : resourcesUrl + dataForm.frontCanvasParamObj.unWhiteBoard"
-                v-if="dataForm.frontCanvasParamObj && dataForm.frontCanvasParamObj.unWhiteBoard"/>
-            </div>
-            <el-upload v-else
-                       class="avatar-uploader"
-                       accept="image/jpg"
-                       :before-upload="(file, fileList)=>handleBeforeUpload(file, fileList,dataForm)"
-                       :action="$http.adornUrl('/admin/file/simpleUpload')"
-                       :headers="{Authorization: $cookie.get('Authorization_vp'),locale:lang}"
-                       :on-success="(res,file)=>{onUploadSuccess(dataForm.frontCanvasParamObj, 'unWhiteBoard',res,file)}"
-                       :show-file-list="false">
-              <el-image v-if="dataForm.frontCanvasParamObj && dataForm.frontCanvasParamObj.unWhiteBoard" style="width: 295px; height: 452px" :src="resourcesUrl + dataForm.frontCanvasParamObj.unWhiteBoard" class="avatar"/>
-            </el-upload>
-          </el-form-item>
-          <el-button v-if="mode==='edit' && dataForm.frontCanvasParamObj && dataForm.frontCanvasParamObj.unWhiteBoard" type="primary" size="mini" style="margin-right: 5px" @click="saveOrUpdateCanvasParam()">保存</el-button>
-        </el-col>
-        <el-col :span="4">
-          <el-form-item>
-            <h2>正面光油层</h2>
-            <div v-if="mode === 'view'">
-              <el-image
-                style="width: 295px; height: 452px"
-                :src="dataForm.frontCanvasParamObj.varnish.indexOf('https://') !== -1? dataForm.frontCanvasParamObj.varnish : resourcesUrl + dataForm.frontCanvasParamObj.varnish"
-                v-if="dataForm.frontCanvasParamObj && dataForm.frontCanvasParamObj.varnish"/>
-            </div>
-            <el-upload v-else
-                       class="avatar-uploader"
-                       accept="image/jpg"
-                       :before-upload="(file, fileList)=>handleBeforeUpload(file, fileList,dataForm)"
-                       :action="$http.adornUrl('/admin/file/simpleUpload')"
-                       :headers="{Authorization: $cookie.get('Authorization_vp'),locale:lang}"
-                       :on-success="(res,file)=>{onUploadSuccess(dataForm.frontCanvasParamObj, 'varnish',res,file)}"
-                       :show-file-list="false">
-              <el-image v-if="dataForm.frontCanvasParamObj && dataForm.frontCanvasParamObj.varnish" style="width: 295px; height: 452px" :src="resourcesUrl + dataForm.frontCanvasParamObj.varnish" class="avatar"/>
-            </el-upload>
-          </el-form-item>
-          <el-button v-if="mode==='edit' && dataForm.frontCanvasParamObj && dataForm.frontCanvasParamObj.varnish" type="primary" size="mini" style="margin-right: 5px" @click="saveOrUpdateCanvasParam()">保存</el-button>
-        </el-col>
-      </el-row>
-      <el-row>
-        <el-col :span="5">
-          <el-form-item>
-            <h2>背面四色层</h2>
-            <div v-if="mode === 'view'">
-              <el-image
-                style="width: 295px; height: 452px"
-                :src="dataForm.backCanvasParamObj.printed.indexOf('https://') !== -1? dataForm.backCanvasParamObj.printed : resourcesUrl + dataForm.backCanvasParamObj.printed"
-                v-if="dataForm.backCanvasParamObj && dataForm.backCanvasParamObj.printed"/>
-            </div>
-            <el-upload v-else
-                       class="avatar-uploader"
-                       accept="image/jpg"
-                       :before-upload="(file, fileList)=>handleBeforeUpload(file, fileList,dataForm)"
-                       :action="$http.adornUrl('/admin/file/simpleUpload')"
-                       :headers="{Authorization: $cookie.get('Authorization_vp'),locale:lang}"
-                       :on-success="(res,file)=>{onUploadSuccess(dataForm.backCanvasParamObj, 'printed',res,file)}"
-                       :show-file-list="false">
-              <el-image v-if="dataForm.backCanvasParamObj && dataForm.backCanvasParamObj.printed" style="width: 295px; height: 452px" :src="resourcesUrl + dataForm.backCanvasParamObj.printed" class="avatar"/>
-<!--              <i v-if="mode==='edit'  && dataForm.backCanvasParamObj && dataForm.backCanvasParamObj.printed" class="el-icon-plus avatar-uploader-icon"></i>-->
-            </el-upload>
-          </el-form-item>
-          <el-button v-if="mode==='edit' && dataForm.backCanvasParamObj && dataForm.backCanvasParamObj.printed" type="primary" size="mini" style="margin-right: 5px" @click="saveOrUpdateCanvasParam()">保存</el-button>
-        </el-col>
-        <el-col :span="5">
-          <el-form-item>
-            <h2>背面白墨层</h2>
-            <div v-if="mode === 'view'">
-              <el-image
-                style="width: 295px; height: 452px"
-                :src="dataForm.backCanvasParamObj.whiteBoard.indexOf('https://') !== -1? dataForm.backCanvasParamObj.whiteBoard : resourcesUrl + dataForm.backCanvasParamObj.whiteBoard"
-                v-if="dataForm.backCanvasParamObj && dataForm.backCanvasParamObj.whiteBoard"/>
-            </div>
-            <el-upload v-else
-                       class="avatar-uploader"
-                       accept="image/jpg"
-                       :before-upload="(file, fileList)=>handleBeforeUpload(file, fileList,dataForm)"
-                       :action="$http.adornUrl('/admin/file/simpleUpload')"
-                       :headers="{Authorization: $cookie.get('Authorization_vp'),locale:lang}"
-                       :on-success="(res,file)=>{onUploadSuccess(dataForm.backCanvasParamObj, 'whiteBoard',res,file)}"
-                       :show-file-list="false">
-              <el-image v-if="dataForm.backCanvasParamObj && dataForm.backCanvasParamObj.whiteBoard" style="width: 295px; height: 452px" :src="resourcesUrl + dataForm.backCanvasParamObj.whiteBoard" class="avatar"/>
-<!--              <i v-if="mode==='edit'  && dataForm.backCanvasParamObj && dataForm.backCanvasParamObj.whiteBoard" class="el-icon-plus avatar-uploader-icon"></i>-->
-            </el-upload>
-          </el-form-item>
-          <el-button v-if="mode==='edit' && dataForm.backCanvasParamObj && dataForm.backCanvasParamObj.whiteBoard" type="primary" size="mini" style="margin-right: 5px" @click="saveOrUpdateCanvasParam()">保存</el-button>
-        </el-col>
-        <el-col :span="5">
-          <el-form-item>
-            <h2>背面烫色层</h2>
-            <div v-if="mode === 'view'">
-              <el-image
-                style="width: 295px; height: 452px"
-                :src="dataForm.backCanvasParamObj.foilstamping.indexOf('https://') !== -1? dataForm.backCanvasParamObj.foilstamping : resourcesUrl + dataForm.backCanvasParamObj.foilstamping"
-                v-if="dataForm.backCanvasParamObj && dataForm.backCanvasParamObj.foilstamping"/>
-            </div>
-            <el-upload v-else
-                       class="avatar-uploader"
-                       accept="image/jpg"
-                       :before-upload="(file, fileList)=>handleBeforeUpload(file, fileList,dataForm)"
-                       :action="$http.adornUrl('/admin/file/simpleUpload')"
-                       :headers="{Authorization: $cookie.get('Authorization_vp'),locale:lang}"
-                       :on-success="(res,file)=>{onUploadSuccess(dataForm.backCanvasParamObj, 'foilstamping',res,file)}"
-                       :show-file-list="false">
-              <el-image v-if="dataForm.backCanvasParamObj && dataForm.backCanvasParamObj.foilstamping" style="width: 295px; height: 452px" :src="resourcesUrl + dataForm.backCanvasParamObj.foilstamping" class="avatar"/>
-<!--              <i v-if="mode==='edit'  && dataForm.backCanvasParamObj && dataForm.backCanvasParamObj.foilstamping" class="el-icon-plus avatar-uploader-icon"></i>-->
-            </el-upload>
-          </el-form-item>
-          <el-button v-if="mode==='edit' && dataForm.backCanvasParamObj && dataForm.backCanvasParamObj.foilstamping" type="primary" size="mini" style="margin-right: 5px" @click="saveOrUpdateCanvasParam()">保存</el-button>
-        </el-col>
-        <el-col :span="5">
-          <el-form-item>
-            <h2>背面逆向层</h2>
-            <div v-if="mode === 'view'">
-              <el-image
-                style="width: 295px; height: 452px"
-                :src="dataForm.backCanvasParamObj.unWhiteBoard.indexOf('https://') !== -1? dataForm.backCanvasParamObj.unWhiteBoard : resourcesUrl + dataForm.backCanvasParamObj.unWhiteBoard"
-                v-if="dataForm.backCanvasParamObj && dataForm.backCanvasParamObj.unWhiteBoard"/>
-            </div>
-            <el-upload v-else
-                       class="avatar-uploader"
-                       accept="image/jpg"
-                       :before-upload="(file, fileList)=>handleBeforeUpload(file, fileList,dataForm)"
-                       :action="$http.adornUrl('/admin/file/simpleUpload')"
-                       :headers="{Authorization: $cookie.get('Authorization_vp'),locale:lang}"
-                       :on-success="(res,file)=>{onUploadSuccess(dataForm.backCanvasParamObj, 'unWhiteBoard',res,file)}"
-                       :show-file-list="false">
-              <el-image v-if="dataForm.backCanvasParamObj && dataForm.backCanvasParamObj.unWhiteBoard" style="width: 295px; height: 452px" :src="resourcesUrl + dataForm.backCanvasParamObj.unWhiteBoard" class="avatar"/>
-<!--              <i v-if="mode==='edit'  && dataForm.backCanvasParamObj && dataForm.backCanvasParamObj.unWhiteBoard" class="el-icon-plus avatar-uploader-icon"></i>-->
-            </el-upload>
-          </el-form-item>
-          <el-button v-if="mode==='edit' && dataForm.backCanvasParamObj && dataForm.backCanvasParamObj.unWhiteBoard" type="primary" size="mini" style="margin-right: 5px" @click="saveOrUpdateCanvasParam()">保存</el-button>
-        </el-col>
-        <el-col :span="4">
-          <el-form-item>
-            <h2>背面光油层</h2>
-            <div v-if="mode === 'view'">
-              <el-image
-                style="width: 295px; height: 452px"
-                :src="dataForm.backCanvasParamObj.varnish.indexOf('https://') !== -1? dataForm.backCanvasParamObj.varnish : resourcesUrl + dataForm.backCanvasParamObj.varnish"
-                v-if="dataForm.backCanvasParamObj && dataForm.backCanvasParamObj.varnish"/>
-            </div>
-            <el-upload v-else
-                       class="avatar-uploader"
-                       accept="image/jpg"
-                       :before-upload="(file, fileList)=>handleBeforeUpload(file, fileList,dataForm)"
-                       :action="$http.adornUrl('/admin/file/simpleUpload')"
-                       :headers="{Authorization: $cookie.get('Authorization_vp'),locale:lang}"
-                       :on-success="(res,file)=>{onUploadSuccess(dataForm.backCanvasParamObj, 'varnish',res,file)}"
-                       :show-file-list="false">
-              <el-image v-if="dataForm.backCanvasParamObj && dataForm.backCanvasParamObj.varnish" style="width: 295px; height: 452px" :src="resourcesUrl + dataForm.backCanvasParamObj.varnish" class="avatar"/>
-<!--              <i v-if="mode==='edit'  && dataForm.backCanvasParamObj && dataForm.backCanvasParamObj.varnish" class="el-icon-plus avatar-uploader-icon"></i>-->
-            </el-upload>
-          </el-form-item>
-          <el-button v-if="mode==='edit'  && dataForm.backCanvasParamObj && dataForm.backCanvasParamObj.varnish" type="primary" size="mini" style="margin-right: 5px" @click="saveOrUpdateCanvasParam()">保存</el-button>
-        </el-col>
-      </el-row>
+      <div v-for="(dataForm, index) in canvasParamList">
+        <el-divider content-position="left">卡项{{index + 1}}</el-divider>
+        <el-row>
+          <el-col :span="5">
+            <el-form-item>
+              <h2>正面四色层</h2>
+              <div v-if="mode === 'view'">
+                <el-image
+                  style="width: 295px; height: 452px"
+                  :src="dataForm.frontCanvasParamObj.printed.indexOf('https://') !== -1? dataForm.frontCanvasParamObj.printed : resourcesUrl + dataForm.frontCanvasParamObj.printed"
+                  v-if="dataForm.frontCanvasParamObj && dataForm.frontCanvasParamObj.printed"/>
+              </div>
+              <el-upload v-else
+                         class="avatar-uploader"
+                         accept="image/jpg"
+                         :before-upload="(file, fileList)=>handleBeforeUpload(file, fileList,dataForm)"
+                         :action="$http.adornUrl('/admin/file/simpleUpload')"
+                         :headers="{Authorization: $cookie.get('Authorization_vp'),locale:lang}"
+                         :on-success="(res,file)=>{onUploadSuccess(dataForm.frontCanvasParamObj, 'printed',res,file)}"
+                         :show-file-list="false">
+                <el-image v-if="dataForm.frontCanvasParamObj && dataForm.frontCanvasParamObj.printed" style="width: 295px; height: 452px" :src="resourcesUrl + dataForm.frontCanvasParamObj.printed" class="avatar"/>
+              </el-upload>
+            </el-form-item>
+            <el-button v-if="mode==='edit' && dataForm.frontCanvasParamObj && dataForm.frontCanvasParamObj.printed" type="primary" size="mini" style="margin-right: 5px" @click="saveOrUpdateCanvasParam(dataForm)">保存</el-button>
+          </el-col>
+          <el-col :span="5">
+            <el-form-item>
+              <h2>正面白墨层</h2>
+              <div v-if="mode === 'view'">
+                <el-image
+                  style="width: 295px; height: 452px"
+                  :src="dataForm.frontCanvasParamObj.whiteBoard.indexOf('https://') !== -1? dataForm.frontCanvasParamObj.whiteBoard : resourcesUrl + dataForm.frontCanvasParamObj.whiteBoard"
+                  v-if="dataForm.frontCanvasParamObj && dataForm.frontCanvasParamObj.whiteBoard"/>
+              </div>
+              <el-upload v-else
+                         class="avatar-uploader"
+                         accept="image/jpg"
+                         :before-upload="(file, fileList)=>handleBeforeUpload(file, fileList,dataForm)"
+                         :action="$http.adornUrl('/admin/file/simpleUpload')"
+                         :headers="{Authorization: $cookie.get('Authorization_vp'),locale:lang}"
+                         :on-success="(res,file)=>{onUploadSuccess(dataForm.frontCanvasParamObj, 'whiteBoard',res,file)}"
+                         :show-file-list="false">
+                <el-image v-if="dataForm.frontCanvasParamObj && dataForm.frontCanvasParamObj.whiteBoard" style="width: 295px; height: 452px" :src="resourcesUrl + dataForm.frontCanvasParamObj.whiteBoard" class="avatar"/>
+              </el-upload>
+            </el-form-item>
+            <el-button v-if="mode==='edit' && dataForm.frontCanvasParamObj && dataForm.frontCanvasParamObj.whiteBoard" type="primary" size="mini" style="margin-right: 5px" @click="saveOrUpdateCanvasParam(dataForm)">保存</el-button>
+          </el-col>
+          <el-col :span="5">
+            <el-form-item>
+              <h2>正面烫色层</h2>
+              <div v-if="mode === 'view'">
+                <el-image
+                  style="width: 295px; height: 452px"
+                  :src="dataForm.frontCanvasParamObj.foilstamping.indexOf('https://') !== -1? dataForm.frontCanvasParamObj.foilstamping : resourcesUrl + dataForm.frontCanvasParamObj.foilstamping"
+                  v-if="dataForm.frontCanvasParamObj && dataForm.frontCanvasParamObj.foilstamping"/>
+              </div>
+              <el-upload v-else
+                         class="avatar-uploader"
+                         accept="image/jpg"
+                         :before-upload="(file, fileList)=>handleBeforeUpload(file, fileList,dataForm)"
+                         :action="$http.adornUrl('/admin/file/simpleUpload')"
+                         :headers="{Authorization: $cookie.get('Authorization_vp'),locale:lang}"
+                         :on-success="(res,file)=>{onUploadSuccess(dataForm.frontCanvasParamObj, 'foilstamping',res,file)}"
+                         :show-file-list="false">
+                <el-image v-if="dataForm.frontCanvasParamObj && dataForm.frontCanvasParamObj.foilstamping" style="width: 295px; height: 452px" :src="resourcesUrl + dataForm.frontCanvasParamObj.foilstamping" class="avatar"/>
+              </el-upload>
+            </el-form-item>
+            <el-button v-if="mode==='edit' && dataForm.frontCanvasParamObj && dataForm.frontCanvasParamObj.foilstamping" type="primary" size="mini" style="margin-right: 5px" @click="saveOrUpdateCanvasParam(dataForm)">保存</el-button>
+          </el-col>
+          <el-col :span="5">
+            <el-form-item>
+              <h2>正面逆向层</h2>
+              <div v-if="mode === 'view'">
+                <el-image
+                  style="width: 295px; height: 452px"
+                  :src="dataForm.frontCanvasParamObj.unWhiteBoard.indexOf('https://') !== -1? dataForm.frontCanvasParamObj.unWhiteBoard : resourcesUrl + dataForm.frontCanvasParamObj.unWhiteBoard"
+                  v-if="dataForm.frontCanvasParamObj && dataForm.frontCanvasParamObj.unWhiteBoard"/>
+              </div>
+              <el-upload v-else
+                         class="avatar-uploader"
+                         accept="image/jpg"
+                         :before-upload="(file, fileList)=>handleBeforeUpload(file, fileList,dataForm)"
+                         :action="$http.adornUrl('/admin/file/simpleUpload')"
+                         :headers="{Authorization: $cookie.get('Authorization_vp'),locale:lang}"
+                         :on-success="(res,file)=>{onUploadSuccess(dataForm.frontCanvasParamObj, 'unWhiteBoard',res,file)}"
+                         :show-file-list="false">
+                <el-image v-if="dataForm.frontCanvasParamObj && dataForm.frontCanvasParamObj.unWhiteBoard" style="width: 295px; height: 452px" :src="resourcesUrl + dataForm.frontCanvasParamObj.unWhiteBoard" class="avatar"/>
+              </el-upload>
+            </el-form-item>
+            <el-button v-if="mode==='edit' && dataForm.frontCanvasParamObj && dataForm.frontCanvasParamObj.unWhiteBoard" type="primary" size="mini" style="margin-right: 5px" @click="saveOrUpdateCanvasParam(dataForm)">保存</el-button>
+          </el-col>
+          <el-col :span="4">
+            <el-form-item>
+              <h2>正面光油层</h2>
+              <div v-if="mode === 'view'">
+                <el-image
+                  style="width: 295px; height: 452px"
+                  :src="dataForm.frontCanvasParamObj.varnish.indexOf('https://') !== -1? dataForm.frontCanvasParamObj.varnish : resourcesUrl + dataForm.frontCanvasParamObj.varnish"
+                  v-if="dataForm.frontCanvasParamObj && dataForm.frontCanvasParamObj.varnish"/>
+              </div>
+              <el-upload v-else
+                         class="avatar-uploader"
+                         accept="image/jpg"
+                         :before-upload="(file, fileList)=>handleBeforeUpload(file, fileList,dataForm)"
+                         :action="$http.adornUrl('/admin/file/simpleUpload')"
+                         :headers="{Authorization: $cookie.get('Authorization_vp'),locale:lang}"
+                         :on-success="(res,file)=>{onUploadSuccess(dataForm.frontCanvasParamObj, 'varnish',res,file)}"
+                         :show-file-list="false">
+                <el-image v-if="dataForm.frontCanvasParamObj && dataForm.frontCanvasParamObj.varnish" style="width: 295px; height: 452px" :src="resourcesUrl + dataForm.frontCanvasParamObj.varnish" class="avatar"/>
+              </el-upload>
+            </el-form-item>
+            <el-button v-if="mode==='edit' && dataForm.frontCanvasParamObj && dataForm.frontCanvasParamObj.varnish" type="primary" size="mini" style="margin-right: 5px" @click="saveOrUpdateCanvasParam(dataForm)">保存</el-button>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="5">
+            <el-form-item>
+              <h2>背面四色层</h2>
+              <div v-if="mode === 'view'">
+                <el-image
+                  style="width: 295px; height: 452px"
+                  :src="dataForm.backCanvasParamObj.printed.indexOf('https://') !== -1? dataForm.backCanvasParamObj.printed : resourcesUrl + dataForm.backCanvasParamObj.printed"
+                  v-if="dataForm.backCanvasParamObj && dataForm.backCanvasParamObj.printed"/>
+              </div>
+              <el-upload v-else
+                         class="avatar-uploader"
+                         accept="image/jpg"
+                         :before-upload="(file, fileList)=>handleBeforeUpload(file, fileList,dataForm)"
+                         :action="$http.adornUrl('/admin/file/simpleUpload')"
+                         :headers="{Authorization: $cookie.get('Authorization_vp'),locale:lang}"
+                         :on-success="(res,file)=>{onUploadSuccess(dataForm.backCanvasParamObj, 'printed',res,file)}"
+                         :show-file-list="false">
+                <el-image v-if="dataForm.backCanvasParamObj && dataForm.backCanvasParamObj.printed" style="width: 295px; height: 452px" :src="resourcesUrl + dataForm.backCanvasParamObj.printed" class="avatar"/>
+                <!--              <i v-if="mode==='edit'  && dataForm.backCanvasParamObj && dataForm.backCanvasParamObj.printed" class="el-icon-plus avatar-uploader-icon"></i>-->
+              </el-upload>
+            </el-form-item>
+            <el-button v-if="mode==='edit' && dataForm.backCanvasParamObj && dataForm.backCanvasParamObj.printed" type="primary" size="mini" style="margin-right: 5px" @click="saveOrUpdateCanvasParam(dataForm)">保存</el-button>
+          </el-col>
+          <el-col :span="5">
+            <el-form-item>
+              <h2>背面白墨层</h2>
+              <div v-if="mode === 'view'">
+                <el-image
+                  style="width: 295px; height: 452px"
+                  :src="dataForm.backCanvasParamObj.whiteBoard.indexOf('https://') !== -1? dataForm.backCanvasParamObj.whiteBoard : resourcesUrl + dataForm.backCanvasParamObj.whiteBoard"
+                  v-if="dataForm.backCanvasParamObj && dataForm.backCanvasParamObj.whiteBoard"/>
+              </div>
+              <el-upload v-else
+                         class="avatar-uploader"
+                         accept="image/jpg"
+                         :before-upload="(file, fileList)=>handleBeforeUpload(file, fileList,dataForm)"
+                         :action="$http.adornUrl('/admin/file/simpleUpload')"
+                         :headers="{Authorization: $cookie.get('Authorization_vp'),locale:lang}"
+                         :on-success="(res,file)=>{onUploadSuccess(dataForm.backCanvasParamObj, 'whiteBoard',res,file)}"
+                         :show-file-list="false">
+                <el-image v-if="dataForm.backCanvasParamObj && dataForm.backCanvasParamObj.whiteBoard" style="width: 295px; height: 452px" :src="resourcesUrl + dataForm.backCanvasParamObj.whiteBoard" class="avatar"/>
+                <!--              <i v-if="mode==='edit'  && dataForm.backCanvasParamObj && dataForm.backCanvasParamObj.whiteBoard" class="el-icon-plus avatar-uploader-icon"></i>-->
+              </el-upload>
+            </el-form-item>
+            <el-button v-if="mode==='edit' && dataForm.backCanvasParamObj && dataForm.backCanvasParamObj.whiteBoard" type="primary" size="mini" style="margin-right: 5px" @click="saveOrUpdateCanvasParam(dataForm)">保存</el-button>
+          </el-col>
+          <el-col :span="5">
+            <el-form-item>
+              <h2>背面烫色层</h2>
+              <div v-if="mode === 'view'">
+                <el-image
+                  style="width: 295px; height: 452px"
+                  :src="dataForm.backCanvasParamObj.foilstamping.indexOf('https://') !== -1? dataForm.backCanvasParamObj.foilstamping : resourcesUrl + dataForm.backCanvasParamObj.foilstamping"
+                  v-if="dataForm.backCanvasParamObj && dataForm.backCanvasParamObj.foilstamping"/>
+              </div>
+              <el-upload v-else
+                         class="avatar-uploader"
+                         accept="image/jpg"
+                         :before-upload="(file, fileList)=>handleBeforeUpload(file, fileList,dataForm)"
+                         :action="$http.adornUrl('/admin/file/simpleUpload')"
+                         :headers="{Authorization: $cookie.get('Authorization_vp'),locale:lang}"
+                         :on-success="(res,file)=>{onUploadSuccess(dataForm.backCanvasParamObj, 'foilstamping',res,file)}"
+                         :show-file-list="false">
+                <el-image v-if="dataForm.backCanvasParamObj && dataForm.backCanvasParamObj.foilstamping" style="width: 295px; height: 452px" :src="resourcesUrl + dataForm.backCanvasParamObj.foilstamping" class="avatar"/>
+                <!--              <i v-if="mode==='edit'  && dataForm.backCanvasParamObj && dataForm.backCanvasParamObj.foilstamping" class="el-icon-plus avatar-uploader-icon"></i>-->
+              </el-upload>
+            </el-form-item>
+            <el-button v-if="mode==='edit' && dataForm.backCanvasParamObj && dataForm.backCanvasParamObj.foilstamping" type="primary" size="mini" style="margin-right: 5px" @click="saveOrUpdateCanvasParam(dataForm)">保存</el-button>
+          </el-col>
+          <el-col :span="5">
+            <el-form-item>
+              <h2>背面逆向层</h2>
+              <div v-if="mode === 'view'">
+                <el-image
+                  style="width: 295px; height: 452px"
+                  :src="dataForm.backCanvasParamObj.unWhiteBoard.indexOf('https://') !== -1? dataForm.backCanvasParamObj.unWhiteBoard : resourcesUrl + dataForm.backCanvasParamObj.unWhiteBoard"
+                  v-if="dataForm.backCanvasParamObj && dataForm.backCanvasParamObj.unWhiteBoard"/>
+              </div>
+              <el-upload v-else
+                         class="avatar-uploader"
+                         accept="image/jpg"
+                         :before-upload="(file, fileList)=>handleBeforeUpload(file, fileList,dataForm)"
+                         :action="$http.adornUrl('/admin/file/simpleUpload')"
+                         :headers="{Authorization: $cookie.get('Authorization_vp'),locale:lang}"
+                         :on-success="(res,file)=>{onUploadSuccess(dataForm.backCanvasParamObj, 'unWhiteBoard',res,file)}"
+                         :show-file-list="false">
+                <el-image v-if="dataForm.backCanvasParamObj && dataForm.backCanvasParamObj.unWhiteBoard" style="width: 295px; height: 452px" :src="resourcesUrl + dataForm.backCanvasParamObj.unWhiteBoard" class="avatar"/>
+                <!--              <i v-if="mode==='edit'  && dataForm.backCanvasParamObj && dataForm.backCanvasParamObj.unWhiteBoard" class="el-icon-plus avatar-uploader-icon"></i>-->
+              </el-upload>
+            </el-form-item>
+            <el-button v-if="mode==='edit' && dataForm.backCanvasParamObj && dataForm.backCanvasParamObj.unWhiteBoard" type="primary" size="mini" style="margin-right: 5px" @click="saveOrUpdateCanvasParam(dataForm)">保存</el-button>
+          </el-col>
+          <el-col :span="4">
+            <el-form-item>
+              <h2>背面光油层</h2>
+              <div v-if="mode === 'view'">
+                <el-image
+                  style="width: 295px; height: 452px"
+                  :src="dataForm.backCanvasParamObj.varnish.indexOf('https://') !== -1? dataForm.backCanvasParamObj.varnish : resourcesUrl + dataForm.backCanvasParamObj.varnish"
+                  v-if="dataForm.backCanvasParamObj && dataForm.backCanvasParamObj.varnish"/>
+              </div>
+              <el-upload v-else
+                         class="avatar-uploader"
+                         accept="image/jpg"
+                         :before-upload="(file, fileList)=>handleBeforeUpload(file, fileList,dataForm)"
+                         :action="$http.adornUrl('/admin/file/simpleUpload')"
+                         :headers="{Authorization: $cookie.get('Authorization_vp'),locale:lang}"
+                         :on-success="(res,file)=>{onUploadSuccess(dataForm.backCanvasParamObj, 'varnish',res,file)}"
+                         :show-file-list="false">
+                <el-image v-if="dataForm.backCanvasParamObj && dataForm.backCanvasParamObj.varnish" style="width: 295px; height: 452px" :src="resourcesUrl + dataForm.backCanvasParamObj.varnish" class="avatar"/>
+                <!--              <i v-if="mode==='edit'  && dataForm.backCanvasParamObj && dataForm.backCanvasParamObj.varnish" class="el-icon-plus avatar-uploader-icon"></i>-->
+              </el-upload>
+            </el-form-item>
+            <el-button v-if="mode==='edit'  && dataForm.backCanvasParamObj && dataForm.backCanvasParamObj.varnish" type="primary" size="mini" style="margin-right: 5px" @click="saveOrUpdateCanvasParam(dataForm)">保存</el-button>
+          </el-col>
+        </el-row>
+      </div>
+
     </el-form>
   </el-dialog>
 
@@ -258,37 +262,55 @@
         lang: localStorage.getItem('lang') || 'zh_CN',
         mode: 'view',
         visible: false,
-        dataForm:{},
+        // dataForm:{},
         resourcesUrl: process.env.VUE_APP_RESOURCES_URL,
+        canvasParamList: [],
       };
     },
     mounted() {
     },
     methods: {
-      init(cardItem){
+      initByOrderNumber(orderItem){
+        this.getCardItemByOrderNumber(orderItem)
+        this.visible = true;
+      },
+      initByItem(cardItem){
         this.getCardItemById(cardItem)
         this.visible = true;
       },
       closeDialog(){
         this.visible = false
-        this.dataForm = {}
+        this.canvasParamList = []
       },
       getCardItemById(cardItem){
         this.$http({
           url: this.$http.adornUrl('/prod/orderCardItem/info/' + cardItem.cardItemId),
           method: 'get',
         }).then(({data}) => {
-          this.dataForm = data;
+          this.canvasParamList.push(data)
+          // this.dataForm = data[0];
+        })
+      },
+      getCardItemByOrderNumber(cardItem){
+        this.$http({
+          url: this.$http.adornUrl('/prod/orderCardItem/list'),
+          method: 'get',
+          params: this.$http.adornParams({orderNumber: cardItem.orderNumber})
+        }).then(({data}) => {
+          this.canvasParamList = data;
         })
       },
       handleBeforeUpload(file, fileList, item){
-        let isSize = true;
+        let isSize = true
         //如果当前是编辑的小卡,就需要判断是否符合尺寸
-        let width = 709;
-        let height = 1087;
+        let width = 709
+        let height = 1087
         let prodName = item.prodName;
         isSize = new Promise(function(resolve, reject) {
-          if(prodName.indexOf("闪卡") !== -1){
+          if(prodName.indexOf("大3寸") !== -1){
+            width = 803
+            height = 1098
+          }else if(prodName.indexOf("闪卡") !== -1){
             width = 709;
             height = 1087;
           }else if(prodName.indexOf("明信片") !== -1){
@@ -326,22 +348,22 @@
         this.$set(item, field,response.filePath);
         this.$forceUpdate()
       },
-      saveOrUpdateCanvasParam(){
+      saveOrUpdateCanvasParam(dataForm){
         this.$confirm('确定要更新吗?', '提示', {
           confirmButtonText: '确定',
           cancelButtonText: '取消',
           type: 'warning'
         }).then(() => {
-          if(this.dataForm.frontCanvasParamObj){
-            this.dataForm.frontCanvasParam = JSON.stringify(this.dataForm.frontCanvasParamObj)
+          if(dataForm.frontCanvasParamObj){
+            dataForm.frontCanvasParam = JSON.stringify(dataForm.frontCanvasParamObj)
           }
-          if(this.dataForm.backCanvasParamObj){
-            this.dataForm.backCanvasParam = JSON.stringify(this.dataForm.backCanvasParamObj)
+          if(dataForm.backCanvasParamObj){
+            dataForm.backCanvasParam = JSON.stringify(dataForm.backCanvasParamObj)
           }
           this.$http({
             url: this.$http.adornUrl('/prod/orderCardItem/saveOrUpdateCanvasParam'),
             method: 'post',
-            data: this.$http.adornData(this.dataForm)
+            data: this.$http.adornData(dataForm)
           }).then(({ data }) =>{
             if(data){
               // this.$set(this.dataForm, 'cardItemId', data.cardItemId);
@@ -357,5 +379,16 @@
 </script>
 
 <style scoped>
+  .el-divider__text.is-left {
+    color: red;
+    left: 0;
+    font-weight: bold;
+    margin: 0 10px;
+    padding: 0 5px;
+    font-size: 20px;
+  }
+  .el-divider {
+    background-color: red;
+  }
 
 </style>

+ 1 - 1
src/components/order-addr-update/index.vue

@@ -19,7 +19,7 @@
       <el-alert :title="this.$i18n.t('components.consultWithUsers')" type="warning" show-icon></el-alert>
       <br />
       <el-form-item :label="this.$i18n.t('publics.addressee')" prop="receiver">
-        <el-input size="small" maxlength="15" v-model="dataForm.receiver" :placeholder="this.$i18n.t('shop.consigneeName')"></el-input>
+        <el-input size="small" maxlength="25" v-model="dataForm.receiver" :placeholder="this.$i18n.t('shop.consigneeName')"></el-input>
       </el-form-item>
 
       <el-form-item :label="this.$i18n.t('publics.mobilePhone')" prop="mobile">

+ 15 - 4
src/components/order-card-item/index.vue

@@ -4,6 +4,7 @@
       <div v-if="showFlagBtn">
         <el-radio v-model="mode" label="view">预览模式</el-radio>
         <el-radio v-model="mode" label="edit">编辑模式</el-radio>
+        <el-button @click="openCanvasParamPicFormByOrderNumber(orderItem)" size="mini" type="text" v-if="orderItem.prodName.indexOf('简约') !== -1 || orderItem.prodName.indexOf('高阶') !== -1">查看工艺</el-button>
       </div>
 
       <div style="border: 2px solid pink; display: inline-block;margin-right: 5px;" v-for="(item, index) in cardItemList" :key="item.cardItemId">
@@ -55,8 +56,8 @@
           <el-button v-if="item.flag==0 && mode=='view'" type="success" size="mini" style="margin-right: 20px" @click="handleFlag(item, index)">待标记</el-button>
           <el-button v-if="item.flag==1 && mode=='view'" type="warning" size="mini" style="margin-right: 5px" @click="handleFlag(item, index)">已标记</el-button>
             <el-button v-if="mode=='view'" type="text" size="mini" @click="openOrgPicForm(item, index)">原图</el-button>
-            <el-button v-if="mode=='view' && (orderItem.prodName.indexOf('简约') !== -1 || orderItem.prodName.indexOf('高阶') !== -1)" type="text" size="mini" @click="openCanvasParamPicForm(item, index)">工艺</el-button>
-          <el-button v-if="item.prodName.indexOf('语音') !== -1 && mode=='view'" type="text" size="mini" @click="openYYForm(item, index)">查看语音</el-button>
+            <el-button v-if="mode=='view' && (orderItem.prodName.indexOf('简约') !== -1 || orderItem.prodName.indexOf('高阶') !== -1)" type="text" size="mini" @click="openCanvasParamPicFormByItem(item, index)">工艺</el-button>
+          <el-button v-if="(item.prodName.indexOf('语音') !== -1 || item.prodName.toLowerCase().indexOf('ar') !== -1) && mode=='view'" type="text" size="mini" @click="openYYForm(item, index)">查看语音</el-button>
           <el-button v-if="mode==='edit'" type="primary" size="mini" style="margin-right: 5px" @click="addOrUpdateCardItem(item)">保存</el-button>
           <el-button v-if="mode==='edit' && item.cardItemId" type="danger" size="mini" style="margin-right: 5px" @click="deleteCardItem(item, index)">删除</el-button>
         </span>
@@ -136,9 +137,14 @@
           this.$refs.orgPicPreviewRef.init(item)
         })
       },
-      openCanvasParamPicForm(item, index){
+      openCanvasParamPicFormByOrderNumber(orderItem, index){
         this.$nextTick(() =>{
-          this.$refs.canvasParamPicPreviewRef.init(item)
+          this.$refs.canvasParamPicPreviewRef.initByOrderNumber(orderItem)
+        })
+      },
+      openCanvasParamPicFormByItem(cardItem, index){
+        this.$nextTick(() =>{
+          this.$refs.canvasParamPicPreviewRef.initByItem(cardItem)
         })
       },
       previewLoad(event){
@@ -170,6 +176,9 @@
           }else if(prodName.indexOf("二宫格") !== -1){
             width = 1252;
             height = 732;
+          }else if(prodName.indexOf("AR明信片") !== -1){
+            width = 1252;
+            height = 1819;
           }else if(prodName.indexOf("明信片") !== -1){
             width = 1229;
             height = 1796;
@@ -362,6 +371,8 @@
           this.prodType = '直拍封面';
         }else if(prodName.indexOf('票根') != -1){
           this.prodType = '票根';
+        }else if(prodName.indexOf('AR明信片') != -1){
+          this.prodType = 'AR明信片';
         }else if(prodName.indexOf('明信片') != -1){
           this.prodType = '明信片';
         }else if(prodName.indexOf('田字四宫格') != -1){

+ 74 - 6
src/components/yuyin-preview/index.vue

@@ -42,13 +42,23 @@
           </el-form-item>
         </el-col>
         <el-col :span="dataForm.cardNote.type === 'AI' ? 12 : 8">
-          <el-form-item label="语音内容">
-            <el-button size="mini" @click="changeAudio">更换音频</el-button>
+          <el-form-item label="语音/视频内容">
+            <el-button size="mini" @click="changeAudio" v-if="dataForm.cardNote.type === 'AI' || dataForm.cardNote.type === 'NORMAL'">更换音频</el-button>
+            <el-button size="mini" @click="changeVideo" v-if="dataForm.cardNote.type === 'AR'">更换视频</el-button>
             <br/>
+            <span size="mini" v-if="dataForm.cardNote.type === 'AR'">原始分辨率:{{dataForm.cardNote.originVideoWidth + "x" + dataForm.cardNote.originVideoHeight}}</span>
+            <br/>
+            <span size="mini" v-if="dataForm.cardNote.type === 'AR'">检测的分辨率:{{videoResolution}}</span>
             <video v-if="dataForm.cardNote.audioUrl"
                    style="width: 300px; height: 210px"
                    :src="resourcesUrl + dataForm.cardNote.audioUrl"
                    controls="controls"/>
+            <video v-if="dataForm.cardNote.videoUrl"
+                   ref="myVideo"
+                   style="width: 330px; height: 210px"
+                   @loadedmetadata="getVideoResolution"
+                   :src="resourcesUrl + dataForm.cardNote.videoUrl"
+                   controls="controls"/>
           </el-form-item>
         </el-col>
         <el-col :span="dataForm.cardNote.type === 'AI' ? 12 : 8" v-if="newAudioUrl">
@@ -60,24 +70,36 @@
               controls="controls"/>
           </el-form-item>
         </el-col>
+        <el-col :span="dataForm.cardNote.type === 'AR' ? 12 : 8" v-if="newVideoUrl">
+          <el-form-item label="新视频">
+            <br/>
+            <video
+              style="width: 300px; height: 210px"
+              :src="resourcesUrl + newVideoUrl"
+              controls="controls"/>
+          </el-form-item>
+        </el-col>
       </el-row>
       <el-form-item>
         <div style="width: 100%; text-align: center;">
-          <el-button v-if="!(dataForm.cardNote.type === 'AI')" type="primary" size="large" @click="repairVideo">转换语音</el-button>
+          <el-button v-if="(dataForm.cardNote.type === 'AI' || dataForm.cardNote.type === 'NORMAL')" type="primary" size="large" @click="repairVideo">转换语音</el-button>
+          <el-button v-if="dataForm.cardNote.type === 'AR'" type="primary" size="large" @click="adjustVideo">调整视频</el-button>
           <el-button type="success" size="large" @click="confirmChangeVideo">确认更换</el-button>
           <el-button type="success" size="large" @click="onSave">保存</el-button>
         </div>
       </el-form-item>
     </el-form>
     <audio-box v-if="audioBoxVisible" ref="audioBox" @refreshPic="refreshAudio"></audio-box>
+    <video-box v-if="videoBoxVisible" ref="videoBox" @refreshPic="refreshVideo"></video-box>
   </el-dialog>
 </template>
 
 <script>
   import AudioBox from '@/components/AudioBox'
+  import VideoBox from '@/components/VideoBox'
   export default {
     components: {
-      AudioBox
+      AudioBox, VideoBox
     },
     name: "YuyinPreview",
     data() {
@@ -85,25 +107,62 @@
         authorNameEdit: true,
         personalSignEdit: true,
         audioBoxVisible: false,
+        videoBoxVisible: false,
         visible: false,
         dataForm:{cardNote:{}, qrNoteMapping:{}},
         newAudioUrl: null,
+        newVideoUrl: null,
         resourcesUrl: process.env.VUE_APP_RESOURCES_URL,
-        transLoading: false
+        transLoading: false,
+        videoResolution:""
       };
     },
     mounted() {
     },
     methods: {
+      getVideoResolution(detail){
+        let video = this.$refs.myVideo;
+        if (video) {
+          this.videoResolution = `${video.videoWidth}x${video.videoHeight}`
+          this.dataForm.cardNote.originVideoWidth = video.videoWidth
+          this.dataForm.cardNote.originVideoHeight = video.videoHeight
+        }
+      },
       changeAudio(){
         this.audioBoxVisible = true
         this.$nextTick(() => {
           this.$refs.audioBox.init(1)
         })
       },
+      changeVideo(){
+        this.videoBoxVisible = true
+        this.$nextTick(() => {
+          this.$refs.videoBox.init(1)
+        })
+      },
       refreshAudio(filePath){
         this.newAudioUrl = filePath;
       },
+      refreshVideo(filePath){
+        this.newVideoUrl = filePath;
+      },
+      adjustVideo() {
+        this.$confirm('确定要调整视频吗?', '提示', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning'
+        }).then(() => {
+          this.$http({
+            url: this.$http.adornUrl('/platform/qrNoteMapping/adjustVideoResolution'),
+            method: 'POST',
+            data: this.dataForm.cardNote
+          }).then(({ data }) =>{
+            if(data){
+              this.newVideoUrl = data.newVideoUrl
+            }
+          })
+        });
+      },
       onSave(){
         this.$http({
           url: this.$http.adornUrl('/platform/cardNote'),
@@ -117,6 +176,9 @@
             this.$message.error("保存失败")
           }
         })
+        this.dataForm = {cardNote:{}, qrNoteMapping:{}}
+        this.newAudioUrl = null
+        this.newVideoUrl = null
       },
       syncTTS(){
         this.$http({
@@ -197,7 +259,12 @@
         });
       },
       confirmChangeVideo(){
-        this.dataForm.cardNote.audioUrl = this.newAudioUrl;
+        if(this.newAudioUrl){
+          this.dataForm.cardNote.audioUrl = this.newAudioUrl;
+        }
+        if(this.newVideoUrl){
+          this.dataForm.cardNote.videoUrl = this.newVideoUrl;
+        }
         /*this.$confirm('确定要保存新语音吗?', '提示', {
           confirmButtonText: '确定',
           cancelButtonText: '取消',
@@ -221,6 +288,7 @@
         this.visible = false
         this.dataForm = {cardNote:{}, qrNoteMapping:{}}
         this.newAudioUrl = null
+        this.newVideoUrl = null
       }
     },
   }

+ 931 - 0
src/views/modules/prod/card-common-lib.vue

@@ -0,0 +1,931 @@
+<template>
+  <div class="mod-home">
+    <div class="search-bar">
+      <el-form :inline="true" class="search-form" ref="searchForm" :model="searchForm" size="small">
+        <div class="input-row">
+          <el-form-item prop="status" label="团体组合" class="search-form-item">
+            <el-select v-model="searchForm.seriesId" placeholder="请选择所属团体组合" clearable filterable @change="selectSeries">
+              <el-option v-for="series in seriesList" :label="series.seriesName" :value="series.seriesId"></el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item prop="status" label="正面爱豆" class="search-form-item">
+            <el-select v-model="searchForm.frontPersonId" placeholder="请选择爱豆" clearable filterable>
+              <el-option v-for="person in personList" :label="person.personName" :value="person.id"></el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item prop="personId" label="背面爱豆" class="search-form-item">
+            <el-select v-model="searchForm.backPersonId" placeholder="请选择爱豆" clearable filterable multiple>
+              <el-option v-for="person in personList" :label="person.personName" :value="person.id"></el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item prop="status" label="正/背面" class="search-form-item">
+            <el-select v-model="searchForm.cardSide" placeholder="请选择卡面或背面库" clearable>
+              <el-option label="卡面库" value="Front"></el-option>
+              <el-option label="卡背库" value="Back"></el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item prop="status" label="年份" class="search-form-item">
+            <el-select v-model="searchForm.year" placeholder="请选择年份" clearable>
+              <el-option v-for="year in years" :label="year.label" :value="year.value"></el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item prop="status" label="是否已加入图集" class="search-form-item">
+            <el-select v-model="searchForm.inCardLib" placeholder="请是否已加入图集" clearable>
+              <el-option label="否" value="0"></el-option>
+              <el-option label="是" value="1"></el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item>
+            <div class="default-btn primary-btn" @click="searchChange(true)">{{$t('crud.searchBtn')}}</div>
+            <div class="default-btn" @click="resetSearchForm('searchForm')">{{$t('product.reset')}}</div>
+          </el-form-item>
+        </div>
+      </el-form>
+    </div>
+    <div class="default-btn primary-btn" @click="openUploadDialog">上传图片</div>
+    <div v-if="(mode === 'chooseMtO' || mode === 'chooseOtO') && selectFrontNum > 0 && selectBackNum > 0" class="default-btn primary-btn" @click="openCreateCardLibDialog">创建图集</div>
+    <div v-if="(mode === 'chooseMtO' || mode === 'chooseOtO') && selectFrontNum > 0 && selectBackNum > 0" class="default-btn primary-btn" @click="openAddCardLibDialog">加入已有图集</div>
+    <div style="margin-top: 10px">
+      <el-radio v-model="mode" label="view">预览模式</el-radio>
+      <el-radio v-model="mode" label="edit">编辑模式</el-radio>
+      <el-radio v-model="mode" label="chooseMtO">选图模式(多对一)</el-radio>
+      <el-radio v-model="mode" label="chooseOtO">选图模式(一对一)</el-radio>
+      <span v-if="(mode === 'chooseMtO' || mode === 'chooseOtO')" style="color: red; font-size: 16px;font-weight: bold">已选卡面/卡背:{{selectFrontNum}}/{{selectBackNum}}</span>
+    </div>
+    <div class="card-plate">
+      <!-- 正面 -->
+      <div class="card-box" @scroll="frontScrollEvent">
+        <div class="card-item">
+          <div class="cardContainer">
+            <div style="display: inline-block;margin-right: 5px;" v-for="(front, index) in frontList" :key="front.id">
+              <el-row :gutter="24" style="padding-top: 5px">
+                <el-col :span="24">
+                  <div :style="(mode === 'chooseMtO' || mode === 'chooseOtO') && front.isSelected? divLightStyle : {border: '3px solid #fff'}" @click="frontItemSelect(front)">
+                    <span class="item-num" v-if="front.num">{{ front.num }}</span>
+                    <el-card :body-style="{ padding: '0px' }">
+                      <div style="padding: 3px; text-align: center">
+                        <span>{{front.seriesName}}</span>
+                        <br/>
+                        <span>{{front.personName}}</span>
+                      </div>
+                      <div style="width: 120px;height: auto">
+                        <img :src="resourcesUrl + front.frontUrl"/>
+                      </div>
+                    </el-card>
+                  </div>
+                </el-col>
+              </el-row>
+              <el-row style="display: flex; justify-content: center">
+                <el-button v-if="mode==='edit' && front.id" type="danger" size="mini" style="margin-right: 5px" @click="deleteCardItem(front, index, 'Front')">删除</el-button>
+              </el-row>
+            </div>
+            <div class="loadMore" @click="loadMore('Front')">
+              <span>点击加载更多</span>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <!-- 背面 -->
+      <div class="card-box" @scroll="backScrollEvent">
+        <div class="card-item">
+          <div class="cardContainer">
+            <div style="display: inline-block;margin-right: 5px;" v-for="(back, index) in backList" :key="back.id">
+              <el-row :gutter="24" style="padding-top: 5px">
+                <el-col :span="24">
+                  <div :style="(mode === 'chooseMtO' || mode === 'chooseOtO') && back.isSelected? divLightStyle : {border: '3px solid #fff'}" @click="backItemSelect(back)">
+                    <span class="item-num" v-if="back.num">{{ back.num }}</span>
+                    <el-card :body-style="{ padding: '0px' }">
+                      <div style="padding: 3px; text-align: center">
+                        <span>{{back.seriesName}}</span>
+                        <br/>
+                        <span>{{back.personName}}</span>
+                      </div>
+                      <div style="width: 120px;height: auto">
+                        <img :src="resourcesUrl + back.backUrl"/>
+                      </div>
+                    </el-card>
+                  </div>
+                </el-col>
+              </el-row>
+              <el-row style="display: flex; justify-content: center">
+                <el-button v-if="mode==='edit' && back.id" type="danger" size="mini" style="margin-right: 5px" @click="deleteCardItem(back, index, 'Back')">删除</el-button>
+              </el-row>
+            </div>
+            <div class="loadMore" @click="loadMore('Back')">
+              <span>点击加载更多</span>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+    <el-dialog :visible.sync="uploadCardVisible" :modal="false" title="上传图片" width="60%" top="3vh" :close-on-click-modal="false">
+      <el-form :inline="true" class="search-form" ref="searchForm" :model="uploadCardData" label-width="auto" size="small">
+        <!-- 表单项 -->
+        <div class="input-row">
+          <el-form-item prop="seriesId" label="团队组合">
+            <el-select v-model="uploadCardData.seriesId" clearable filterable @change="selectSeries">
+              <el-option
+                v-for="node in seriesList"
+                :key="node.seriesId"
+                :label="node.seriesName"
+                :value="node.seriesId"
+              ></el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item prop="personId" label="爱豆" class="search-form-item">
+            <el-select v-model="uploadCardData.personId" placeholder="请选择爱豆" clearable filterable>
+              <el-option v-for="person in personList" :label="person.personName" :value="person.id"></el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item prop="cardSide" label="正背面">
+            <el-select v-model="uploadCardData.cardSide" clearable filterable>
+              <el-option :key="1" label="正面" :value="'Front'"></el-option>
+              <el-option :key="2" label="背面" :value="'Back'"></el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item prop="cardType" label="卡类型">
+            <el-select v-model="uploadCardData.cardType" clearable filterable>
+              <el-option :key="1" label="3寸小卡" :value="'3CXK'"></el-option>
+              <el-option :key="2" label="3寸拍立得" :value="'3CFP'"></el-option>
+              <el-option :key="3" label="明信片" :value="'MXP'"></el-option>
+              <el-option :key="4" label="书签" :value="'SQ'"></el-option>
+              <el-option :key="5" label="大方卡" :value="'FK'"></el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item prop="picYear" label="年份">
+            <el-select v-model="uploadCardData.picYear" clearable filterable>
+              <el-option :key="1" label="2025年" :value="'2025'"></el-option>
+              <el-option :key="2" label="2024年" :value="'2024'"></el-option>
+              <el-option :key="3" label="2024年以前" :value="'2024年以前'"></el-option>
+            </el-select>
+          </el-form-item>
+          <br/>
+          <div v-if="uploadErrorTips" style="color: red; font-size: 18px">{{uploadErrorTips + '尺寸不对'}}</div>
+          <el-form-item prop="files" label="图片">
+            <el-upload
+              ref="upload"
+              list-type="picture-card"
+              accept="image/*"
+              :multiple="true"
+              :auto-upload="false"
+              :on-change="onChangeUpload"
+              action="#"
+              :file-list="fileList">
+              <i class="el-icon-plus"></i>
+            </el-upload>
+          </el-form-item>
+        </div>
+      </el-form>
+      <span slot="footer" class="dialog-footer">
+          <el-button class="default-btn">{{$t("crud.filter.cancelBtn")}}</el-button>
+          <el-button :loading="submitLoading" class="default-btn primary-btn" type="primary" @click="uploadCardSubmit()">{{$t("crud.filter.submitBtn")}}</el-button>
+        </span>
+    </el-dialog>
+    <el-dialog :visible.sync="createCardLibVisible" :modal="false" title="创建图集" width="60%" top="3vh" :close-on-click-modal="false" @close="createCardLibList = []">
+      <el-form :inline="true" class="search-form" ref="searchForm" :model="cardLibData" label-width="auto" size="small">
+        <!-- 表单项 -->
+        <div class="input-row">
+          <el-form-item prop="seriesId" label="团队组合">
+            <el-select v-model="cardLibData.seriesId" clearable filterable @change="selectSeries">
+              <el-option
+                v-for="node in seriesList"
+                :key="node.seriesId"
+                :label="node.seriesName"
+                :value="node.seriesId"
+              ></el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item prop="personId" label="爱豆" class="search-form-item">
+            <el-select v-model="cardLibData.personId" placeholder="请选择爱豆" clearable filterable>
+              <el-option v-for="person in personList" :label="person.personName" :value="person.id"></el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item prop="cardType" label="卡类型">
+            <el-select v-model="cardLibData.cardType" clearable filterable>
+              <el-option :key="1" label="3寸小卡" :value="'3CXK'"></el-option>
+              <el-option :key="2" label="3寸拍立得" :value="'3CFP'"></el-option>
+              <el-option :key="3" label="明信片" :value="'MXP'"></el-option>
+              <el-option :key="4" label="书签" :value="'SQ'"></el-option>
+              <el-option :key="5" label="大方卡" :value="'FK'"></el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item prop="picYear" label="年份">
+            <el-select v-model="cardLibData.picYear" clearable filterable>
+              <el-option :key="1" label="2025年" :value="'2025'"></el-option>
+              <el-option :key="2" label="2024年" :value="'2024'"></el-option>
+              <el-option :key="3" label="2024年以前" :value="'2024年以前'"></el-option>
+            </el-select>
+          </el-form-item>
+          <br/>
+          <div class="create-card-lib" v-for="(card, index) in createCardLibList" :key="index">
+            <el-row :gutter="12" style="padding-top: 5px">
+              <span class="num">{{card.num}}</span>
+              <el-col :span="12">
+                <el-card :body-style="{ padding: '0px' }">
+                  <div style="padding: 3px; text-align: center">
+                    <span>正面</span>
+                  </div>
+                  <div style="width: 100px;height: auto">
+                    <img :src="resourcesUrl + card.frontUrl"/>
+                  </div>
+                </el-card>
+              </el-col>
+              <el-col :span="12">
+                <el-card :body-style="{ padding: '0px' }">
+                  <div style="padding: 3px; text-align: center">
+                    <span>背面</span>
+                  </div>
+                  <div style="width: 100px;height: auto">
+                    <img :src="resourcesUrl + card.backUrl"/>
+                  </div>
+                </el-card>
+              </el-col>
+            </el-row>
+          </div>
+        </div>
+      </el-form>
+      <span slot="footer" class="dialog-footer">
+          <el-button class="default-btn">{{$t("crud.filter.cancelBtn")}}</el-button>
+          <el-button :loading="submitLoading" class="default-btn primary-btn" type="primary" @click="createCardLibSubmit()">{{$t("crud.filter.submitBtn")}}</el-button>
+        </span>
+    </el-dialog>
+    <el-dialog :visible.sync="addCardLibVisible" :modal="false" title="加入到已有图集" width="60%" top="3vh" :close-on-click-modal="false" @close="createCardLibList = []">
+      <el-form :inline="true" class="search-form" ref="searchForm" :model="addCardLibData" label-width="auto" size="small">
+        <!-- 表单项 -->
+        <div class="input-row">
+          <el-form-item prop="libId" label="图集名称">
+            <el-select v-model="addCardLibData.id" clearable filterable>
+              <el-option
+                v-for="lib in cardLibList"
+                :key="lib.id"
+                :label="lib.seriesName + '_' + lib.libNo"
+                :value="lib.id"
+              ></el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item prop="seriesId" label="团队组合">
+            <el-select v-model="addCardLibData.seriesId" clearable filterable @change="selectSeries">
+              <el-option
+                v-for="node in seriesList"
+                :key="node.seriesId"
+                :label="node.seriesName"
+                :value="node.seriesId"
+              ></el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item prop="personId" label="爱豆" class="search-form-item">
+            <el-select v-model="addCardLibData.personId" placeholder="请选择爱豆" clearable filterable>
+              <el-option v-for="person in personList" :label="person.personName" :value="person.id"></el-option>
+            </el-select>
+          </el-form-item>
+          <br/>
+          <div class="create-card-lib" v-for="(card, index) in createCardLibList" :key="index">
+            <el-row :gutter="12" style="padding-top: 5px">
+              <span class="num">{{card.num}}</span>
+              <el-col :span="12">
+                <el-card :body-style="{ padding: '0px' }">
+                  <div style="padding: 3px; text-align: center">
+                    <span>正面</span>
+                  </div>
+                  <div style="width: 100px;height: auto">
+                    <img :src="resourcesUrl + card.frontUrl"/>
+                  </div>
+                </el-card>
+              </el-col>
+              <el-col :span="12">
+                <el-card :body-style="{ padding: '0px' }">
+                  <div style="padding: 3px; text-align: center">
+                    <span>背面</span>
+                  </div>
+                  <div style="width: 100px;height: auto">
+                    <img :src="resourcesUrl + card.backUrl"/>
+                  </div>
+                </el-card>
+              </el-col>
+            </el-row>
+          </div>
+        </div>
+      </el-form>
+      <span slot="footer" class="dialog-footer">
+          <el-button class="default-btn">{{$t("crud.filter.cancelBtn")}}</el-button>
+          <el-button :loading="submitLoading" class="default-btn primary-btn" type="primary" @click="addCardLibSubmit()">{{$t("crud.filter.submitBtn")}}</el-button>
+        </span>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+  export default {
+    data() {
+      return {
+        selectFrontNum: 0,
+        selectBackNum: 0,
+        mode: 'view',
+        uploadCardData: {},
+        cardLibData: {},
+        uploadCardVisible: false,
+        createCardLibVisible: false,
+        addCardLibVisible: false,
+        searchForm: {},
+        seriesList: [],
+        personList: [],
+        years: [],
+        dataList: [],
+        uploadErrorTips: '',
+        resourcesUrl: process.env.VUE_APP_RESOURCES_URL,
+        frontPage: {
+          total: 0, // 总页数
+          currentPage: 1, // 当前页数
+          pageSize: 50 // 每页显示多少条
+        },
+        backPage: {
+          total: 0, // 总页数
+          currentPage: 1, // 当前页数
+          pageSize: 50 // 每页显示多少条
+        },
+        frontList: [],
+        backList:[],
+        waterfallFlowFrontContainerWidth: 0,
+        waterfallFlowBackContainerWidth: 0,
+        cardColNum: 5,
+        cardMargin: 10,
+        columnHeights:[],
+        fileList: [],
+        createCardLibList: [],
+        submitLoading: false,
+        divLightStyle: {border: '3px solid red'},
+        cardLibList: [],
+        addCardLibData: {}
+      }
+    },
+    mounted(){
+
+    },
+    watch: {
+      mode () {
+        if (this.mode === 'chooseMtO' || this.mode === 'chooseOtO') {
+          this.frontList.forEach(item => {
+            item.isSelected = false
+            item.num = 0
+          })
+          this.backList.forEach(item => {
+            item.isSelected = false
+            item.num = 0
+          })
+          this.selectFrontNum = 0
+          this.selectBackNum = 0
+        }
+      }
+    },
+    created() {
+      this.getCardFrontLib()
+      this.getCardBackLib()
+      this.getSeriesList()
+      this.initSelectYear(new Date().getFullYear())
+
+    },
+    methods: {
+      resetSearchForm(){
+        this.searchForm = {}
+      },
+      deleteCardItem(item, index, cardSide){
+        this.$confirm('确定要删除吗?', '提示', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning'
+        }).then(() => {
+          let url = cardSide === 'Front' ?  '/cardLib/cardFrontLib/' : '/cardLib/cardBackLib/'
+          this.$http({
+            url: this.$http.adornUrl(url + item.id),
+            method: 'delete',
+          }).then(({ data }) =>{
+            if(data){
+              if(cardSide === 'Front'){
+                this.$delete(this.frontList, index)
+              }
+              if(cardSide === 'Back'){
+                this.$delete(this.backList, index)
+              }
+              this.$message.success("删除成功")
+            }else{
+              this.$message.error("删除失败")
+            }
+          })
+        });
+      },
+      frontItemSelect (front) {
+        if (this.mode === 'chooseMtO' || this.mode === 'chooseOtO') {
+          let idx = this.frontList.findIndex(item => item.id === front.id)
+          if (idx !== -1) {
+            if (front.isSelected) {
+              front.isSelected = false
+              if (this.selectFrontNum !== 0) {
+                this.selectFrontNum = this.selectFrontNum - 1
+              }
+            } else {
+              front.isSelected = true
+              this.selectFrontNum = this.selectFrontNum + 1
+            }
+            if (this.mode === 'chooseOtO') {
+              if (front.isSelected) {
+                front.num = this.selectFrontNum
+              } else {
+                this.backList.forEach(item => {
+                  if (item.num > front.num) {
+                    item.num = item.num - 1
+                  }
+                })
+                let backIdx = this.backList.findIndex(item => item.num === front.num)
+                if (backIdx !== -1) {
+                  let back = this.backList[backIdx]
+                  back.num = 0
+                  back.isSelected = false
+                  this.selectBackNum = this.selectBackNum - 1
+                  this.$set(this.backList, backIdx, back)
+                }
+                this.frontList.forEach(item => {
+                  if (item.num > front.num) {
+                    item.num = item.num - 1
+                  }
+                })
+                front.num = 0
+              }
+            } else if (this.mode === 'chooseMtO') {
+              if (front.isSelected) {
+                front.num = this.selectFrontNum
+              } else {
+                this.frontList.forEach(item => {
+                  if (item.num > front.num) {
+                    item.num = item.num - 1
+                  }
+                })
+                front.num = 0
+              }
+            }
+            this.$set(this.frontList, idx, front)
+          }
+        }
+      },
+      backItemSelect (back) {
+        if (this.mode === 'chooseMtO' || this.mode === 'chooseOtO') {
+          let idx = this.backList.findIndex(item => item.id === back.id)
+          if (idx !== -1) {
+            if (this.mode === 'chooseMtO') {
+              if (this.selectBackNum !== 0) {
+                let oldIdx = this.backList.findIndex(item => item.isSelected === true)
+                if (oldIdx !== -1) {
+                  let oldSelectedBack = this.backList[oldIdx]
+                  oldSelectedBack.isSelected = false
+                  oldSelectedBack.num--
+                  this.$set(this.backList, oldIdx, oldSelectedBack)
+                  this.selectBackNum = this.selectBackNum - 1
+                }
+              }
+            }
+            if (back.isSelected) {
+              back.isSelected = false
+              if (this.selectBackNum !== 0) {
+                this.selectBackNum = this.selectBackNum - 1
+                back.num = this.selectBackNum
+              }
+            } else {
+              back.isSelected = true
+              this.selectBackNum = this.selectBackNum + 1
+              back.num = this.selectBackNum
+            }
+            if (this.mode === 'chooseOtO') {
+              if (back.isSelected) {
+                back.num = this.selectBackNum
+              } else {
+                this.backList.forEach(item => {
+                  if (item.num > back.num) {
+                    item.num = item.num - 1
+                  }
+                })
+                back.num = 0
+              }
+            }
+            this.$set(this.backList, idx, back)
+          }
+        }
+      },
+      backScrollEvent (e) {
+        if (e.srcElement.scrollTop + e.srcElement.clientHeight + 1 > e.srcElement.scrollHeight){
+          this.loadMore('Back')
+        }
+      },
+      frontScrollEvent (e) {
+        if (e.srcElement.scrollTop + e.srcElement.clientHeight + 1 > e.srcElement.scrollHeight){
+          this.loadMore('Front')
+        }
+      },
+      loadMore (cardSide) {
+        if (cardSide === 'Front') {
+          this.frontPage.currentPage = this.frontPage.currentPage + 1
+          this.getCardFrontLib(true)
+        }
+        if (cardSide === 'Back') {
+          this.backPage.currentPage = this.backPage.currentPage + 1
+          this.getCardBackLib(true)
+        }
+      },
+      searchChange () {
+        this.frontPage.currentPage = 1
+        this.backPage.currentPage = 1
+        if(this.searchForm.cardSide){
+          if (this.searchForm.cardSide === 'Back'){
+            this.getCardBackLib()
+          } else {
+            this.getCardFrontLib()
+          }
+        }else{
+          this.getCardFrontLib()
+          this.getCardBackLib()
+        }
+      },
+      onChangeUpload (file, fileList) {
+        this.fileList = fileList
+        this.handleBeforeUpload(file, fileList)
+      },
+      openUploadDialog () {
+        this.uploadCardVisible = true
+      },
+      openCreateCardLibDialog () {
+        let _this = this
+        this.createCardLibVisible = true
+        let frontList = this.frontList.filter(front => front.num && front.num > 0).sort((max, min) => { return max.num - min.num })
+        let backList = this.backList.filter(back => back.num && back.num > 0).sort((max, min) => { return max.num - min.num })
+        if (this.mode === 'chooseOtO') {
+          frontList.forEach(front => {
+            let back = backList.find(item => item.num === front.num)
+            _this.createCardLibList.push({frontUrl: front.frontUrl, backUrl: back ? back.backUrl : null, num: front.num})
+          })
+        } else if (this.mode === 'chooseMtO') {
+          let back = backList[0]
+          frontList.forEach(front => {
+            _this.createCardLibList.push({frontUrl: front.frontUrl, backUrl: back.backUrl, num: front.num})
+          })
+        }
+      },
+      openAddCardLibDialog () {
+        this.getCardLibList()
+        let _this = this
+        this.addCardLibVisible = true
+        let frontList = this.frontList.filter(front => front.num && front.num > 0).sort((max, min) => { return max.num - min.num })
+        let backList = this.backList.filter(back => back.num && back.num > 0).sort((max, min) => { return max.num - min.num })
+        if (this.mode === 'chooseOtO') {
+          frontList.forEach(front => {
+            let back = backList.find(item => item.num === front.num)
+            _this.createCardLibList.push({frontUrl: front.frontUrl, backUrl: back ? back.backUrl : null, num: front.num})
+          })
+        } else if (this.mode === 'chooseMtO') {
+          let back = backList[0]
+          frontList.forEach(front => {
+            _this.createCardLibList.push({frontUrl: front.frontUrl, backUrl: back.backUrl, num: front.num})
+          })
+        }
+      },
+      uploadCardSubmit () {
+        this.submitLoading = true
+        let formData = new FormData()
+        formData.append('seriesId', this.uploadCardData.seriesId)
+        formData.append('personId', this.uploadCardData.personId)
+        formData.append('year', this.uploadCardData.picYear)
+        formData.append('cardType', this.uploadCardData.cardType)
+        for (let i = 0; i < this.fileList.length; i++) {
+          formData.append('file', this.fileList[i].raw)
+        }
+        let url = this.uploadCardData.cardSide === 'Front' ? '/cardLib/cardFrontLib/saveBatchFromFiles' : '/cardLib/cardBackLib/saveBatchFromFiles'
+        this.$http({
+          url: this.$http.adornUrl(url),
+          method: 'POST',
+          data: formData,
+          headers: {
+            'Content-Type': 'multipart/form-data'
+          }
+        }).then(({data}) => {
+          this.submitLoading = false
+          this.$message({
+            message: '上传成功',
+            type: 'success',
+            duration: 300,
+            onClose: () => {
+              this.uploadCardVisible = false
+              if (this.uploadCardData.cardSide === 'Front') {
+                this.getCardFrontLib()
+              } else {
+                this.getCardBackLib()
+              }
+              this.uploadCardData = {}
+              this.fileList = []
+            }
+          })
+        })
+      },
+      createCardLibSubmit () {
+        this.cardLibData.cardLibItemList = this.createCardLibList
+        this.$http({
+          url: this.$http.adornUrl('/card/cardLib/createCardLib'),
+          method: 'POST',
+          data: this.cardLibData
+        }).then(({data}) => {
+          this.submitLoading = false
+          this.$message({
+            message: '创建成功',
+            type: 'success',
+            duration: 300,
+            onClose: () => {
+              this.createCardLibVisible = false
+            }
+          })
+        })
+      },
+      addCardLibSubmit () {
+        this.addCardLibData.cardLibItemList = this.createCardLibList
+        this.$http({
+          url: this.$http.adornUrl('/card/cardLib/addToCardLib'),
+          method: 'POST',
+          data: this.addCardLibData
+        }).then(({data}) => {
+          this.submitLoading = false
+          this.$message({
+            message: '创建成功',
+            type: 'success',
+            duration: 300,
+            onClose: () => {
+              this.addCardLibVisible = false
+            }
+          })
+        })
+      },
+      selectSeries (value) {
+        this.personList = []
+        this.getPersonList(value)
+      },
+      initSelectYear(year){
+        this.years = [];
+        for (let i = 0; i < 10; i++) {
+          this.years.push({value:(year - i),label:(year - i)+ "年"});
+        }
+        this.years.push({value:null,label:"无年份"});
+      },
+      getSeriesList () {
+        this.$http({
+          url: this.$http.adornUrl('/prod/prodTemplateSeries/page'),
+          method: 'get',
+          params: this.$http.adornParams(
+            Object.assign({
+                size: 100,
+                shopId: 1
+              },
+            )
+          )
+        }).then(({data}) => {
+          this.seriesList = data.records
+        })
+      },
+      getPersonList (seriesId) {
+        this.$http({
+          url: this.$http.adornUrl('/cardLib/cardPerson/page'),
+          method: 'get',
+          params: this.$http.adornParams(
+            Object.assign({
+                size: 100,
+                seriesId: seriesId
+              },
+            )
+          )
+        }).then(({data}) => {
+          this.personList = data.records
+        })
+      },
+      handleSizeChange (val) {
+        this.page.pageSize = val
+        this.getDataList()
+      },
+      handleCurrentChange (val) {
+        this.page.currentPage = val
+        this.getDataList()
+      },
+      getCardFrontLib(isLoadMore){
+        this.$http({
+          url: this.$http.adornUrl('/cardLib/cardFrontLib/page'),
+          method: 'get',
+          params: this.$http.adornParams(
+            Object.assign({
+                size: this.frontPage.pageSize,
+                current: this.frontPage.currentPage,
+                shopId: 1,
+                personId: this.searchForm.frontPersonId
+              },
+              this.searchForm
+            )
+          )
+        }).then(({data}) => {
+          if(isLoadMore){
+            this.frontList.push(...data.records)
+          }else{
+            this.frontList = data.records
+          }
+        })
+      },
+      getCardBackLib(isLoadMore){
+        this.$http({
+          url: this.$http.adornUrl('/cardLib/cardBackLib/page'),
+          method: 'get',
+          params: this.$http.adornParams(
+            Object.assign({
+                size: this.backPage.pageSize,
+                current: this.backPage.currentPage,
+                shopId: 1,
+                personIdList: this.searchForm.backPersonId
+              },
+              this.searchForm
+            )
+          )
+        }).then(({data}) => {
+          if(isLoadMore){
+            this.backList.push(...data.records)
+          }else{
+            this.backList = data.records
+          }
+        })
+      },
+      getCardLibList(){
+        this.$http({
+          url: this.$http.adornUrl('/card/cardLib/page'),
+          method: 'get',
+          params: this.$http.adornParams(
+            Object.assign({
+                size: 200,
+                shopId: 1
+              }
+            )
+          )
+        }).then(({data}) => {
+          this.cardLibList = data.records
+        })
+      },
+      handleBeforeUpload (file, fileList) {
+        let index = fileList.findIndex(item => item.name === file.name)
+        let _this = this
+        let fileType = file.raw.type
+        let isJpg = fileType === 'image/jpg' || fileType === 'image/jpeg'
+        if (!isJpg) {
+          _this.uploadErrorTips = _this.uploadErrorTips + ' 第' + (index + 1) + '张不是jpg图片'
+          return false
+        }
+        let isSize = true
+        let width = 709
+        let height = 1087
+        let cardType = this.uploadCardData.cardType
+        if (cardType === '3CXK' || cardType === '3CFP') {
+          width = 709
+          height = 1087
+        } else if (cardType === '4CXK') {
+          width = 921
+          height = 1087
+        } else if (cardType === 'SQ') {
+          width = 638
+          height = 1796
+        } else if (cardType === 'FK') {
+          width = 1229
+          height = 1229
+        } else if (cardType === 'MXP') {
+          width = 1252
+          height = 1819
+        }
+        isSize = new Promise(function(resolve, reject) {
+          let _URL = window.URL || window.webkitURL
+          let image = new Image()
+          image.onload = function() {
+            let valid = image.naturalWidth === width && image.naturalHeight === height
+            valid ? resolve() : reject()
+          }
+          image.src = _URL.createObjectURL(file.raw)
+        }).then(
+          () => {
+            return file;
+          },
+          () => {
+            _this.uploadErrorTips = _this.uploadErrorTips + ' 第' + (index + 1) + '张,'
+            return Promise.reject()
+          }
+        )
+      }
+    },
+    beforeDestroy() {
+      // let erd = elementResizeDetectorMaker()
+      // erd.uninstall(this.$refs.entirety) // 这里用ref是因为vue离开页面后获取不到dom
+    }
+  }
+</script>
+
+<style lang="scss">
+  // e-chart
+  #real-time-data-chart canvas {
+    width: 100%;
+    height: 100%;
+    padding: 0 20px !important
+  }
+
+  .cardContainer{
+    display: inline-block;
+    margin-right: 5px;
+    width: 100%;
+  }
+  .loadMore{
+    display: flex;
+    justify-content: center;
+    margin-top: 10px;
+    color: blue;
+    cursor: pointer;
+  }
+  .mod-home {
+    .search-bar {
+      .input-row {
+        .select-time-btn {
+          margin-right: 20px;
+          display: inline-block;
+          color: #AAAAAA;
+          font-size: 14px;
+          cursor: pointer;
+
+          &:last-child {
+            margin-right: 0;
+          }
+        }
+
+        .select-time-btn.is-active {
+          color: #155BD4;
+        }
+
+      }
+    }
+
+    /**
+      整体看板
+       */
+    .card-plate {
+      display: flex;
+      flex-wrap: wrap;
+      justify-content: space-between;
+      // 上
+      .card-box {
+        display: flex;
+        flex-wrap: wrap;
+        flex-direction: column;
+        width: 50%;
+        padding: 10px;
+        height: 700px;
+        overflow-y: auto; /* 当内容超出时显示垂直滚动条 */
+        overflow-x: hidden; /* 隐藏水平滚动条 */
+
+        .card-item{
+          display: flex;
+          width: 100%;
+          flex-direction: column;
+          background: #fbfbfb;
+          padding: 10px;
+          box-sizing: border-box;
+          border-radius: 4px;
+          border: 1px solid pink;
+          margin-top: 10px;
+          .item-num{
+            position: absolute;
+            float: left;
+            left:10px;
+            top:0px;
+            font-size: 16px;
+            text-align: center;
+            color: white;
+            background-color: red;
+            border-radius: 100%;
+            width: 20px;
+            height: 20px;
+          }
+        }
+      }
+    }
+    .create-card-lib{
+      border: 2px solid pink;
+      display: inline-block;
+      margin-right: 15px;
+      .num{
+        position: absolute;
+        display:flex;
+        justify-content: center;
+        align-items: center;
+        left: 5px;
+        top: 0px;
+        color: white;
+        border-radius: 100%;
+        background-color: red;
+        width: 20px;
+        height: 20px
+      }
+    }
+  }
+</style>
+

+ 230 - 0
src/views/modules/prod/card-set-lib-add-or-update.vue

@@ -0,0 +1,230 @@
+<template>
+  <el-dialog
+    @close="closeDialog"
+    title="图集模板"
+    :close-on-click-modal="false"
+    width="80%"
+    top="5vh"
+    :visible.sync="visible">
+    <el-form :model="dataForm" :rules="dataRule" ref="dataForm" label-width="80px">
+      <el-form-item label="图集名称" prop="seriesName">
+        <span>{{dataForm.seriesName}}</span>
+      </el-form-item>
+    </el-form>
+    <div v-if="mode === 'choose' && selectNum > 0" class="default-btn primary-btn" @click="openAddToGroupBuyDialog">加入团购</div>
+    <div>
+      <el-radio v-model="mode" label="view">预览模式</el-radio>
+      <el-radio v-model="mode" label="edit">编辑模式</el-radio>
+      <el-radio v-model="mode" label="choose">选图模式</el-radio>
+      <el-radio v-model="mode" label="check">检测模式</el-radio>
+      <span v-if="(mode === 'choose')" style="color: red; font-size: 16px;font-weight: bold">已选数量:{{selectNum}}</span>
+    </div>
+    <div class="create-card-lib" v-for="(cardItem, index) in cardLibItemList" :key="index">
+        <div :style="(mode === 'choose' && cardItem.isSelected? divLightStyle : {border: '3px solid #fff'})" @click="mode==='choose'? cardItemSelect(cardItem) : (mode==='check'? cardItemCheck(cardItem): '')">
+          <el-row :gutter="12" style="padding-top: 5px">
+            <el-col :span="12">
+              <el-card :body-style="{ padding: '0px' }">
+                <div style="padding: 3px; text-align: center">
+                  <span>正面</span>
+                </div>
+                <div style="width: 100px;height: auto">
+                  <img :src="resourcesUrl + cardItem.frontUrl"/>
+                </div>
+              </el-card>
+            </el-col>
+            <el-col :span="12">
+              <el-card :body-style="{ padding: '0px' }">
+                <div style="padding: 3px; text-align: center">
+                  <span>背面</span>
+                </div>
+                <div style="width: 100px;height: auto">
+                  <img :src="resourcesUrl + cardItem.backUrl"/>
+                </div>
+              </el-card>
+            </el-col>
+          </el-row>
+        </div>
+        <el-row style="width: 210px; height: 30px; text-align: center ;color: red; font-weight: bold">
+          <el-button v-if="mode==='edit' && cardItem.id" type="danger" size="mini" style="margin-right: 5px" @click="deleteCardItem(cardItem, index)">删除</el-button>
+        </el-row>
+      </div>
+    <span slot="footer" class="dialog-footer">
+      <el-button class="default-btn" @click="visible = false">{{$t("crud.filter.cancelBtn")}}</el-button>
+    </span>
+    <el-dialog
+      title="团购选择"
+      :close-on-click-modal="false"
+      :append-to-body="true"
+      :visible.sync="addToGroupBuyVisible">
+      <el-form
+        ref="dataForm"
+        size="small"
+        label-width="auto"
+        :model="groupBuyData">
+        <el-form-item label="选择团购" prop="prodType">
+          <el-select style="width: 300px" v-model="groupBuyData.prodId" clearable filterable>
+            <el-option v-for="(prod, index) in prodList"
+                       :key="prod.prodId"
+                       :label="prod.prodName"
+                       :value="prod.prodId">
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item prop="category" label="分类:">
+          <el-input style="width: 300px" v-model="groupBuyData.category" type="text" clearable placeholder="请输入分类"></el-input>
+        </el-form-item>
+      </el-form>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="closeDialog">取消</el-button>
+        <el-button type="primary" @click="groupBuyDataSubmit()">确认</el-button>
+      </span>
+    </el-dialog>
+  </el-dialog>
+</template>
+
+<script>
+export default {
+
+  data () {
+    return {
+      mode: 'view',
+      resourcesUrl: process.env.VUE_APP_RESOURCES_URL,
+      visible: false,
+      dataForm: {
+        seriesId: null,
+        seriesName: null,
+        shopId: 1
+      },
+      cardLibItemList: [],
+      dataRule: {
+      },
+      selectNum: 0,
+      divLightStyle: {border: '3px solid red'},
+      addToGroupBuyVisible: false,
+      groupBuyData: {},
+      prodList: []
+    }
+  },
+  methods: {
+    init (cardLib) {
+      this.dataForm.seriesName = cardLib.seriesName
+      this.dataForm.seriesId = cardLib.seriesId
+      this.visible = true
+      this.$nextTick(() => {
+        this.$http({
+          url: this.$http.adornUrl('/card/cardLibItem/page'),
+          method: 'get',
+          params: this.$http.adornParams(
+            Object.assign({
+                size: 500,
+                shopId: 1,
+                cardLibId: cardLib.id
+              }
+            )
+          )
+        }).then(({data}) => {
+          this.cardLibItemList = data.records
+        })
+      })
+    },
+    groupBuyDataSubmit(){
+      let cardLibItemList = this.cardLibItemList.filter(item => item.isSelected === true)
+      this.groupBuyData.cardLibItemList = cardLibItemList
+      this.$http({
+        url: this.$http.adornUrl('/print/printPicLib/addFromCardSetLib'),
+        method: 'post',
+        data: this.$http.adornData(this.groupBuyData)
+      }).then(({data}) => {
+        this.$message({
+          message: this.$i18n.t('publics.operation'),
+          type: 'success',
+          duration: 300,
+          onClose: () => {
+            this.closeDialog()
+          }
+        })
+      })
+    },
+    deleteCardItem(item, index){
+      this.$confirm('确定要删除吗?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        this.$http({
+          url: this.$http.adornUrl('/card/cardLibItem/' + item.id),
+          method: 'delete',
+        }).then(({ data }) =>{
+          if(data){
+            this.$delete(this.cardLibItemList, index);
+            this.$message.success("删除成功");
+          }else{
+            this.$message.error("删除失败");
+          }
+        })
+      });
+    },
+    cardItemSelect(cardItem){
+      let idx = this.cardLibItemList.findIndex(item => item.id === cardItem.id)
+      if (idx !== -1) {
+        if (cardItem.isSelected) {
+          cardItem.isSelected = false
+          if (this.selectNum !== 0) {
+            this.selectNum = this.selectNum - 1
+          }
+        } else {
+          cardItem.isSelected = true
+          this.selectNum = this.selectNum + 1
+        }
+        this.$set(this.cardLibItemList, idx, cardItem)
+      }
+    },
+    cardItemCheck(cardItem){
+      this.$http({
+        url: this.$http.adornUrl('/card/cardLib/checkCardLibSize'),
+        method: 'post',
+        data: this.$http.adornData(cardItem)
+      }).then(({data}) => {
+        this.$message({
+          message: '检测正常',
+          type: 'success',
+          duration: 500,
+        })
+      })
+    },
+    openAddToGroupBuyDialog(){
+      this.addToGroupBuyVisible = true
+      this.getGroupBuyProdList()
+    },
+    getGroupBuyProdList(){
+      this.$http({
+        url: this.$http.adornUrl('/prod/prod/getProdPage'),
+        method: 'get',
+        params: this.$http.adornParams(
+          Object.assign({
+              current: 1,
+              size: 200,
+              shopId: 1,
+              customType: 2
+            },
+          )
+        )
+      }).then(({data}) => {
+        this.prodList = data.records
+      })
+    },
+    closeDialog(){
+      this.dataForm = {}
+      this.selectNum = 0
+      this.mode = 'view'
+    },
+  }
+}
+</script>
+<style scoped>
+  .create-card-lib {
+    border: 2px solid pink;
+    display: inline-block;
+    margin-right: 15px
+  }
+</style>

+ 199 - 0
src/views/modules/prod/card-set-lib.vue

@@ -0,0 +1,199 @@
+<template>
+  <div class="mod-prod-prodTemplateSeries">
+    <!-- 搜索相关区域 -->
+    <div class="search-bar">
+      <el-form :inline="true" class="search-form" ref="searchForm" :model="searchForm" label-width="auto" size="small">
+        <div class="input-row">
+          <el-form-item prop="seriesName" label="团队组合" class="search-form-item">
+            <el-select v-model="searchForm.seriesId" placeholder="请选择所属团体组合" :filterable="true" :remote="true" :clearable="true"
+                       :remote-method="getSeriesList" :loading="searchLoading">
+              <el-option v-for="series in seriesList" :label="series.seriesName" :value="series.seriesId"></el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item>
+            <div class="default-btn primary-btn" @click="searchChange(searchForm)">{{$t('crud.searchBtn')}}</div>
+            <div class="default-btn" @click="resetSearchForm('searchForm')">{{$t('shop.resetMap')}}</div>
+          </el-form-item>
+        </div>
+      </el-form>
+    </div>
+    <!-- 列表相关区域 -->
+    <div class="main-container">
+      <div class="table-con spec-table">
+        <el-table
+          ref="specListTable"
+          :data="dataList"
+          header-cell-class-name="table-header"
+          row-class-name="table-row"
+          style="width: 100%">
+          <!-- 系列名称 -->
+          <el-table-column label="图集团队组合名称" prop="seriesName" align="center">
+            <template slot-scope="scope">
+              <span>{{ scope.row.seriesName}}</span>
+            </template>
+          </el-table-column>
+          <el-table-column label="图集编号" prop="seq" align="center">
+            <template slot-scope="scope">
+              <span>{{ scope.row.libNo}}</span>
+            </template>
+          </el-table-column>
+          <!-- 成员名称 -->
+          <el-table-column label="成员名称" prop="usageList" align="center" width="600px">
+            <template slot-scope="scope">
+              <div class="table-cell-text">{{ (scope.row.personList != null && scope.row.personList.length > 0)? scope.row.personList.join('/'): "" }}</div>
+            </template>
+          </el-table-column>
+
+          <el-table-column align="center" fixed="right" :label="$t('publics.operating')" width="auto">
+            <template slot-scope="scope">
+              <div class="text-btn-con">
+                <div class="default-btn text-btn" @click="addOrUpdateHandle(scope.row)">{{$t("crud.updateBtn")}}</div>
+                <div class="default-btn text-btn" @click.stop="deleteHandle(scope.row.id)">{{$t("text.delBtn")}}</div>
+                </div>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+        <el-pagination
+          v-if="dataList.length"
+          @size-change="handleSizeChange"
+          @current-change="handleCurrentChange"
+          :current-page="page.currentPage"
+          :page-sizes="[10, 20, 50, 100]"
+          :page-size="page.pageSize"
+          layout="total, sizes, prev, pager, next, jumper"
+          :total="page.total">
+        </el-pagination>
+      </div>
+    <add-or-update v-if="addOrUpdateVisible" ref="addOrUpdate" @refreshDataList="refreshChange"></add-or-update>
+    <add-or-update-person v-if="addOrUpdatePersonVisible" ref="addOrUpdatePerson" @refreshDataList="refreshChange"></add-or-update-person>
+  </div>
+</template>
+
+<script>
+import AddOrUpdate from './card-set-lib-add-or-update'
+import AddOrUpdatePerson from './cardPerson-add-or-update'
+export default {
+  data () {
+    return {
+      dataList: [],
+      page: {
+        total: 0, // 总页数
+        currentPage: 1, // 当前页数
+        pageSize: 10 // 每页显示多少条
+      },
+      searchForm: {}, // 搜索
+      dataListLoading: false,
+      addOrUpdateVisible: false,
+      addOrUpdatePersonVisible: false,
+      usageList:[],
+      seriesList: [],
+      searchLoading: false,
+    }
+  },
+  components: {
+    AddOrUpdate, AddOrUpdatePerson
+  },
+  created () {
+    this.getDataList()
+  },
+  mounted () {
+  },
+  methods: {
+    getSeriesList (seriesName) {
+      this.$http({
+        url: this.$http.adornUrl('/prod/prodTemplateSeries/list'),
+        method: 'get',
+        params: this.$http.adornParams(
+          Object.assign({
+              size: 100,
+              seriesName: seriesName
+            }
+          )
+        )
+      }).then(({data}) => {
+        this.seriesList = data
+      })
+    },
+    getDataList (page) {
+      this.dataListLoading = true
+      this.$http({
+        url: this.$http.adornUrl('/card/cardLib/page'),
+        method: 'get',
+        params: this.$http.adornParams(
+          Object.assign({
+            current: page == null ? this.page.currentPage : page.currentPage,
+            size: page == null ? this.page.pageSize : page.pageSize,
+          },
+            this.searchForm
+          )
+        )
+      }).then(({data}) => {
+        this.dataList = data.records
+        this.page.total = data.total
+        this.dataListLoading = false
+        this.seriesList = this.dataList
+      })
+    },
+    // 新增 / 修改
+    addOrUpdateHandle (cardLib) {
+      this.addOrUpdateVisible = true
+      this.$nextTick(() => {
+        this.$refs.addOrUpdate.init(cardLib)
+      })
+    },
+    deleteHandle (id) {
+      this.$confirm(this.$i18n.t('admin.isDeleOper') + '?', this.$i18n.t('text.tips'), {
+        confirmButtonText: this.$i18n.t('crud.filter.submitBtn'),
+        cancelButtonText: this.$i18n.t('crud.filter.cancelBtn'),
+        type: 'warning'
+      }).then(() => {
+        this.$http({
+          url: this.$http.adornUrl('/card/cardLib/' + id),
+          method: 'delete',
+          data: this.$http.adornData({})
+        }).then(({ data }) => {
+          this.$message({
+            message: this.$i18n.t('publics.operation'),
+            type: 'success',
+            duration: 200,
+            onClose: () => {
+              this.refreshChange()
+            }
+          })
+        })
+      }).catch(() => { })
+    },
+    // 刷新回调
+    refreshChange () {
+      // this.page.currentPage = 1
+      this.getDataList(this.page)
+    },
+    searchChange (params) {
+      this.page.currentPage = 1
+      this.searchForm = params
+      this.getDataList(this.page)
+    },
+    handleSizeChange (val) {
+      this.page.pageSize = val
+      this.getDataList()
+    },
+    handleCurrentChange (val) {
+      this.page.currentPage = val
+      this.getDataList()
+    },
+    /**
+     * 重置表单
+     * @param {String} formName 表单名称
+     */
+    resetSearchForm (formName) {
+      this.$refs[formName].resetFields()
+      this.getDataList()
+    }
+  }
+}
+</script>
+<style lang="scss">
+.mod-prod-prodTemplateSeries {
+}
+</style>

+ 144 - 0
src/views/modules/prod/cardPerson-add-or-update.vue

@@ -0,0 +1,144 @@
+<template>
+  <el-dialog
+    title="团队组合成员"
+    :close-on-click-modal="false"
+    :visible.sync="visible"
+    @close="closeDialog">
+    <el-form :model="dataForm" :rules="dataRule" ref="dataForm" label-width="80px">
+      <el-form-item label="团队组合名称" prop="seriesName" label-width="100">
+        <span>{{dataForm.seriesName}}</span>
+      </el-form-item>
+      <el-form-item label="成员名称" prop="seriesUsage">
+        <el-tag
+          :key="tag"
+          v-for="tag in dynamicTags"
+          closable
+          :disable-transitions="false"
+          @close="handleClose(tag)">
+          {{tag}}
+        </el-tag>
+        <el-input
+          class="input-new-tag"
+          v-if="inputVisible"
+          v-model="inputValue"
+          ref="saveTagInput"
+          size="small"
+          @keyup.enter.native="handleInputConfirm"
+          @blur="handleInputConfirm"
+        >
+        </el-input>
+        <el-button v-else class="button-new-tag" size="small" @click="showInput">+ 点击新增</el-button>
+      </el-form-item>
+    </el-form>
+    <span slot="footer" class="dialog-footer">
+      <el-button class="default-btn" @click="visible = false">{{$t("crud.filter.cancelBtn")}}</el-button>
+      <el-button class="default-btn primary-btn" type="primary" @click="dataFormSubmit()">{{$t("crud.filter.submitBtn")}}</el-button>
+    </span>
+  </el-dialog>
+</template>
+
+<script>
+export default {
+  data () {
+    return {
+      visible: false,
+      dataForm: {
+        seriesId: null,
+        seriesName: null,
+        shopId: 1
+      },
+      personList:[],
+      dynamicTags:[],
+      dataRule: {
+      },
+      inputVisible: false,
+      inputValue: null,
+    }
+  },
+  methods: {
+    init (series) {
+      this.visible = true
+      this.$nextTick(() => {
+        this.$refs['dataForm'].resetFields()
+        this.dataForm.seriesId = series.seriesId || 0
+        this.dataForm.seriesName = series.seriesName || 0
+        if (this.dataForm.seriesName) {
+          this.$http({
+            url: this.$http.adornUrl('/cardLib/cardPerson/list'),
+            method: 'get',
+            params: {seriesName: series.seriesName}
+          }).then(({data}) => {
+            this.dynamicTags = data.map(item => item.personName)
+          })
+        }
+      })
+    },
+    handleClose(person) {
+      this.dynamicTags.splice(this.dynamicTags.indexOf(person), 1);
+    },
+
+    showInput() {
+      this.inputVisible = true;
+      this.$nextTick(_ => {
+        this.$refs.saveTagInput.$refs.input.focus();
+      });
+    },
+    closeDialog(){
+      this.dynamicTags = []
+      this.personList =[]
+      this.inputValue = null
+    },
+
+    handleInputConfirm() {
+      let inputValue = this.inputValue;
+      if (inputValue) {
+        this.dynamicTags.push(inputValue);
+      }
+      this.inputVisible = false;
+      this.inputValue = '';
+    },
+    // 表单提交
+    dataFormSubmit () {
+      this.$refs['dataForm'].validate((valid) => {
+        if (valid) {
+          this.dynamicTags.forEach(item =>{
+            this.personList.push({seriesId: this.dataForm.seriesId, seriesName: this.dataForm.seriesName, personName: item})
+          });
+          this.$http({
+            url: this.$http.adornUrl('/cardLib/cardPerson/savePerson'),
+            method: 'post',
+            data: this.$http.adornData({seriesId: this.dataForm.seriesId, seriesName: this.dataForm.seriesName, personList: this.personList})
+          }).then(({data}) => {
+            this.$message({
+              message: this.$i18n.t('publics.operation'),
+              type: 'success',
+              duration: 200,
+              onClose: () => {
+                this.visible = false
+                this.$emit('refreshDataList')
+              }
+            })
+          })
+        }
+      })
+    }
+  }
+}
+</script>
+<style scoped>
+  .el-tag + .el-tag {
+    margin-left: 10px;
+  }
+  .button-new-tag {
+    margin-left: 10px;
+    height: 32px;
+    line-height: 30px;
+    padding-top: 0;
+    padding-bottom: 0;
+  }
+  .input-new-tag {
+    width: 90px;
+    margin-left: 10px;
+    vertical-align: bottom;
+  }
+</style>

+ 192 - 0
src/views/modules/prod/group-buy-lib.vue

@@ -0,0 +1,192 @@
+<template>
+  <div class="mod-print-printPicLib">
+    <!-- 搜索相关区域 -->
+    <div class="search-bar">
+      <el-form :inline="true" class="search-form" ref="searchForm" :model="searchForm" label-width="auto" size="small">
+        <!-- 表单项 -->
+        <div class="input-row">
+          <el-form-item prop="prodId" label="查询产品">
+            <el-input v-model="searchForm.prodName" clearable></el-input>
+          </el-form-item>
+          <el-form-item>
+            <div class="default-btn primary-btn" @click="searchChange()">{{ $t('crud.searchBtn') }}</div>
+            <div class="default-btn" @click="resetForm()">{{ $t('shop.resetMap') }}</div>
+          </el-form-item>
+        </div>
+      </el-form>
+    </div>
+    <!-- 列表相关区域 -->
+    <div class="main-container">
+      <div class="table-con spec-table">
+        <el-table
+          ref="specListTable"
+          :data="dataList"
+          header-cell-class-name="table-header"
+          row-class-name="table-row"
+          style="width: 100%">
+          <!-- 排序序号 -->
+          <el-table-column label="产品ID" prop="prodId" align="center">
+            <template slot-scope="scope">
+              <span>{{ scope.row.prodId}}</span>
+            </template>
+          </el-table-column>
+          <!-- 排序序号 -->
+          <el-table-column label="产品名称" prop="prodName" align="center">
+            <template slot-scope="scope">
+              <span>{{ scope.row.prodName}}</span>
+            </template>
+          </el-table-column>
+          <!-- 正面图 -->
+          <el-table-column label="产品封面" prop="frontUrl" align="center">
+            <template slot-scope="scope">
+              <el-image
+                style="width: 100px; height: 100px"
+                :src="resourcesUrl + scope.row.pic"
+                v-if="scope.row.pic"
+                fit="fill"
+                @click="previewPic(scope.row.pic)"
+              />
+            </template>
+          </el-table-column>
+          <el-table-column align="center" fixed="right" :label="$t('publics.operating')" width="auto">
+            <template slot-scope="scope">
+              <div class="text-btn-con">
+                <div class="default-btn text-btn" @click="addOrUpdateHandle(scope.row)">{{$t("crud.updateBtn")}}</div>
+                </div>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+        <el-pagination
+          v-if="dataList.length"
+          @size-change="handleSizeChange"
+          @current-change="handleCurrentChange"
+          :current-page="page.currentPage"
+          :page-sizes="[10, 20, 50, 100]"
+          :page-size="page.pageSize"
+          layout="total, sizes, prev, pager, next, jumper"
+          :total="page.total">
+        </el-pagination>
+      </div>
+    <add-or-update v-if="addOrUpdateVisible" ref="addOrUpdate" @refreshDataList="refreshChange"></add-or-update>
+    <!--<el-dialog :visible.sync="previewPicDialogVisible" :modal="false" title="图片预览" width="30%" top="3vh">
+      <el-image :src="previewPicUrl" alt=""  style="width: 100%; height: 100%"/>
+    </el-dialog>-->
+  </div>
+</template>
+
+<script>
+import AddOrUpdate from './groupBuyLib-add-or-update'
+export default {
+  data () {
+    return {
+      dataList: [],
+      page: {
+        total: 0, // 总页数
+        currentPage: 1, // 当前页数
+        pageSize: 10 // 每页显示多少条
+      },
+      categoryList:[],
+      prodList:[],
+      previewPicUrl: null,
+      previewPicDialogVisible: false,
+      resourcesUrl: process.env.VUE_APP_RESOURCES_URL,
+      shopId: this.$store.state.user.shopId,
+      searchForm: {
+        prodId: null
+      }, // 搜索
+      dataListLoading: false,
+      addOrUpdateVisible: false
+    }
+  },
+  components: {
+    AddOrUpdate
+  },
+  created () {
+    this.getDataList();
+  },
+  mounted () {
+  },
+  methods: {
+    previewPic (url) {
+      this.previewPicUrl = this.resourcesUrl + url
+      this.previewPicDialogVisible = true
+    },
+    getDataList (page) {
+      this.dataListLoading = true
+      this.$http({
+        url: this.$http.adornUrl('/prod/prod/getProdPage'),
+        method: 'get',
+        params: this.$http.adornParams(
+          Object.assign({
+            current: page == null ? this.page.currentPage : page.currentPage,
+            size: page == null ? this.page.pageSize : page.pageSize,
+            shopId: 1,
+            customType: 2
+          },
+            this.searchForm
+          )
+        )
+      }).then(({data}) => {
+        this.dataList = data.records
+        this.page.total = data.total
+        this.dataListLoading = false
+      })
+    },
+    // 新增 / 修改
+    addOrUpdateHandle (groupBuy) {
+      this.addOrUpdateVisible = true
+      this.$nextTick(() => {
+        this.$refs.addOrUpdate.init(groupBuy)
+      })
+    },
+    deleteHandle (id) {
+      this.$confirm(this.$i18n.t('admin.isDeleOper') + '?', this.$i18n.t('text.tips'), {
+        confirmButtonText: this.$i18n.t('crud.filter.submitBtn'),
+        cancelButtonText: this.$i18n.t('crud.filter.cancelBtn'),
+        type: 'warning'
+      }).then(() => {
+        this.$http({
+          url: this.$http.adornUrl('/print/printPicLib/' + id),
+          method: 'delete',
+          data: this.$http.adornData({})
+        }).then(({ data }) => {
+          this.$message({
+            message: this.$i18n.t('publics.operation'),
+            type: 'success',
+            duration: 500,
+            onClose: () => {
+              this.refreshChange()
+            }
+          })
+        })
+      }).catch(() => { })
+    },
+    // 刷新回调
+    refreshChange () {
+      // this.page.currentPage = 1
+      this.getDataList(this.page)
+    },
+    resetForm () {
+      this.searchForm = {
+        prodId: null
+      }
+    },
+    searchChange (params) {
+      this.getDataList(this.page)
+    },
+    handleSizeChange (val) {
+      this.page.pageSize = val
+      this.getDataList()
+    },
+    handleCurrentChange (val) {
+      this.page.currentPage = val
+      this.getDataList()
+    }
+  }
+}
+</script>
+<style lang="scss">
+.mod-print-printPicLib {
+}
+</style>

+ 173 - 0
src/views/modules/prod/groupBuyLib-add-or-update.vue

@@ -0,0 +1,173 @@
+<template>
+  <el-dialog
+    title="团购详情"
+    width="80%"
+    top="5vh"
+    :close-on-click-modal="false"
+    :visible.sync="visible"
+    @close="closeDialog">
+    <el-form :model="dataForm" :rules="dataRule" ref="dataForm" label-width="100px">
+      <el-form-item label="关联产品" prop="prodId">
+        <span>{{dataForm.prodName}}</span>
+      </el-form-item>
+      <div>
+        <el-radio v-model="mode" label="view">预览模式</el-radio>
+        <el-radio v-model="mode" label="edit">编辑模式</el-radio>
+      </div>
+      <div class="card-box" @scroll="backScrollEvent">
+        <div class="create-card-lib" v-for="(cardItem, index) in cardLibItemList" :key="cardItem.id">
+          <el-row :gutter="12" style="padding-top: 5px">
+            <el-col :span="12">
+              <el-card :body-style="{ padding: '0px' }">
+                <div style="padding: 3px; text-align: center">
+                  <span>正面</span>
+                </div>
+                <div style="width: 100px;height: auto">
+                  <img :src="resourcesUrl + cardItem.frontUrl"/>
+                </div>
+              </el-card>
+            </el-col>
+            <el-col :span="12">
+              <el-card :body-style="{ padding: '0px' }">
+                <div style="padding: 3px; text-align: center">
+                  <span>背面</span>
+                </div>
+                <div style="width: 100px;height: auto">
+                  <img :src="resourcesUrl + cardItem.backUrl"/>
+                </div>
+              </el-card>
+            </el-col>
+          </el-row>
+          <el-row style="width: 210px; height: 30px; text-align: center ;color: red; font-weight: bold">
+            <el-button v-if="mode === 'edit'" type="danger" size="mini" style="margin-right: 5px" @click="deleteCardItem(cardItem, index)">删除</el-button>
+          </el-row>
+        </div>
+      </div>
+
+    </el-form>
+    <span slot="footer" class="dialog-footer">
+      <el-button class="default-btn" @click="visible = false">{{$t("crud.filter.cancelBtn")}}</el-button>
+    </span>
+  </el-dialog>
+</template>
+
+<script>
+export default {
+  components: {
+
+  },
+  data () {
+    return {
+      mode: 'view',
+      visible: false,
+      cardSetLibVisible: false,
+      dataForm: {
+        id: null,
+        frontUrl: null,
+        backUrl: null,
+        prodId: null,
+        prodName: null,
+        seq: null,
+        isDelete: 0,
+        category: null,
+        backCopyNum: 1,
+        shopId: 1,
+      },
+      page: {
+        total: 0, // 总页数
+        currentPage: 1, // 当前页数
+        pageSize: 50 // 每页显示多少条
+      },
+      resourcesUrl: process.env.VUE_APP_RESOURCES_URL,
+      prodList: [],
+      dataRule: {
+      },
+      cardLibItemList: []
+    }
+  },
+  created(){
+
+  },
+  methods: {
+    closeDialog(){
+      this.dataForm = {}
+      this.cardLibItemList = []
+      this.visible = false
+      this.page.currentPage = 1
+      this.mode = 'view'
+    },
+    backScrollEvent (e) {
+      if (e.srcElement.scrollTop + e.srcElement.clientHeight + 1 > e.srcElement.scrollHeight){
+        this.loadMore()
+      }
+    },
+    loadMore () {
+      this.page.currentPage = this.page.currentPage + 1
+      this.getCardItemList(true)
+    },
+    deleteCardItem (cardItem, index) {
+      this.$confirm('确定要删除吗?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        this.$http({
+          url: this.$http.adornUrl('/print/printPicLib/' + cardItem.id),
+          method: 'delete'
+        }).then(({ data }) => {
+          if (data) {
+            this.$delete(this.cardLibItemList, index)
+            this.$message.success('删除成功')
+          } else {
+            this.$message.error('删除失败')
+          }
+        })
+      })
+    },
+    getCardItemList (isLoadMore) {
+      this.$http({
+        url: this.$http.adornUrl('/print/printPicLib/page'),
+        method: 'get',
+        params: this.$http.adornParams(
+          Object.assign({
+              size: this.page.pageSize,
+              current: this.page.currentPage,
+              shopId: 1,
+              prodId: this.dataForm.prodId
+            }
+          ))
+      }).then(({data}) => {
+        if(isLoadMore){
+          this.cardLibItemList.push(...data.records)
+        }else{
+          this.cardLibItemList = data.records
+        }
+      })
+    },
+    init (groupBuy) {
+      this.dataForm.prodId = groupBuy.prodId || null
+      this.dataForm.prodName = groupBuy.prodName || null
+      this.visible = true
+      this.$nextTick(() => {
+        if (this.dataForm.prodId) {
+          this.getCardItemList()
+        }
+      })
+    },
+  }
+}
+</script>
+<style scoped>
+  .card-box {
+    width: 100%;
+    padding: 10px;
+    height: 700px;
+    overflow-y: auto; /* 当内容超出时显示垂直滚动条 */
+    overflow-x: hidden; /* 隐藏水平滚动条 */
+  }
+  .create-card-lib {
+    border: 2px solid pink;
+    display: inline-block;
+    margin-right: 10px
+  }
+</style>

+ 379 - 0
src/views/modules/prod/prodTemplate.vue

@@ -0,0 +1,379 @@
+<template>
+  <div class="mod-prod-prodTemplate">
+    <!-- 搜索相关区域 -->
+    <div class="search-bar">
+      <el-form :inline="true" class="search-form" ref="searchForm" :model="searchForm" label-width="auto" size="small">
+        <!-- 表单项 -->
+        <div class="input-row">
+          <el-form-item prop="templateSeriesId" label="团队组合">
+            <el-select v-model="searchForm.templateSeriesId" clearable filterable>
+              <el-option
+                      v-for="node in seriesList"
+                      :key="node.seriesId"
+                      :label="node.seriesName"
+                      :value="node.seriesId"
+              ></el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item prop="templateSide" label="正背面">
+            <el-select v-model="searchForm.templateSide" clearable filterable>
+              <el-option :key="1" label="正面" :value="'Front'"></el-option>
+              <el-option :key="2" label="背面" :value="'Back'"></el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item prop="templateUsage" label="用途">
+            <el-select v-model="searchForm.templateUsage" clearable filterable>
+              <el-option
+                v-for="node in templateUsageList"
+                :key="node.value"
+                :label="node.label"
+                :value="node.value"
+              ></el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item prop="joinCommonLib" label="是否入库">
+            <el-select v-model="searchForm.joinCommonLib" clearable filterable>
+              <el-option :key="0" label="未入库" :value="0"></el-option>
+              <el-option :key="1" label="已入库" :value="1"></el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item>
+            <div class="default-btn primary-btn" @click="searchChange()">{{ $t('crud.searchBtn') }}</div>
+            <div class="default-btn" @click="resetForm()">{{ $t('shop.resetMap') }}</div>
+          </el-form-item>
+        </div>
+      </el-form>
+    </div>
+    <!-- 列表相关区域 -->
+    <div class="main-container">
+      <div class="operation-bar">
+        <div class="default-btn primary-btn" @click="addOrUpdateHandle()">{{$t("crud.addTitle")}}</div>
+        <div class="default-btn primary-btn" v-if="multipleSelection.length > 0" @click="openClassifyDialog()">归类</div>
+      </div>
+      <div class="table-con spec-table">
+        <el-table
+          ref="specListTable"
+          :data="dataList"
+          header-cell-class-name="table-header"
+          row-class-name="table-row"
+          @selection-change="handleSelectionChange"
+          style="width: 100%">
+          <el-table-column
+            type="selection"
+            width="55">
+          </el-table-column>
+          <el-table-column
+                  align="center"
+                  prop="templatePic"
+                  label="图片"
+                  width="300">
+            <template slot-scope="scope">
+              <el-image
+                  style="width: 100px; height: 100px"
+                  :src="resourcesUrl + scope.row.templatePic"
+                  v-if="scope.row.templatePic"
+                  fit="fill"
+                  @click="previewPic(scope.row)"
+              />
+            </template>
+          </el-table-column>
+          <!-- 模板下风格的系列,比如二次元风格的海贼王系列 -->
+          <el-table-column label="团队组合" prop="templateSeries" align="center">
+            <template slot-scope="scope">
+              <span>{{ scope.row.templateSeries}}</span>
+            </template>
+          </el-table-column>
+          <el-table-column label="图片用途" prop="usageList" align="center">
+            <template slot-scope="scope">
+              <div class="table-cell-text">{{ scope.row.usageList != null? scope.row.usageList.join('/'): "" }}</div>
+            </template>
+          </el-table-column>
+          <!-- 模板面,Front:正面,Back:背面 -->
+          <el-table-column label="正/背面" prop="templateSide" align="center">
+            <template slot-scope="scope">
+              <span v-if="scope.row.templateSide == 'Front'">正面</span>
+              <span v-if="scope.row.templateSide == 'Back'">背面</span>
+            </template>
+          </el-table-column>
+          <el-table-column label="状态" prop="status" align="center">
+            <template slot-scope="scope">
+              <el-tag type="success" v-if="scope.row.status == 1">启用</el-tag>
+              <el-tag type="danger" v-if="scope.row.status == 0">禁用</el-tag>
+            </template>
+          </el-table-column>
+          <el-table-column label="排序" prop="seq" align="center">
+            <template slot-scope="scope">
+              <span>{{ scope.row.seq}}</span>
+            </template>
+          </el-table-column>
+          <el-table-column label="排序" prop="seq" align="center">
+            <template slot-scope="scope">
+              <el-tag type="success" v-if="scope.row.joinCommonLib === 1">已加入</el-tag>
+              <el-tag type="danger" v-else>未加入</el-tag>
+            </template>
+          </el-table-column>
+          <el-table-column align="center" fixed="right" :label="$t('publics.operating')" width="auto">
+            <template slot-scope="scope">
+              <div class="text-btn-con">
+                <div class="default-btn text-btn" @click="addOrUpdateHandle(scope.row.templateId)"
+                     >{{$t("crud.updateBtn")}}</div>
+                <div class="default-btn text-btn" @click.stop="deleteHandle(scope.row.templateId)"
+                     >{{$t("text.delBtn")}}</div>
+                </div>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+        <el-pagination
+          v-if="dataList.length"
+          @size-change="handleSizeChange"
+          @current-change="handleCurrentChange"
+          :current-page="page.currentPage"
+          :page-sizes="[10, 20, 50, 100]"
+          :page-size="page.pageSize"
+          layout="total, sizes, prev, pager, next, jumper"
+          :total="page.total">
+        </el-pagination>
+      </div>
+    <el-dialog :visible.sync="previewPicDialogVisible" :modal="false" title="图片预览" width="30%" top="3vh">
+      <el-image :src="previewPicUrl" alt=""  style="width: 100%; height: 100%"/>
+    </el-dialog>
+    <el-dialog :visible.sync="classifyVisible" :modal="false" title="图片分类" width="30%" top="3vh">
+      <el-form :inline="true" class="search-form" ref="searchForm" :model="searchForm" label-width="auto" size="small">
+        <!-- 表单项 -->
+        <div class="input-row">
+          <el-form-item prop="seriesId" label="团队组合">
+            <el-select v-model="classifyData.seriesId" clearable filterable @change="selectSeries">
+              <el-option
+                v-for="node in seriesList"
+                :key="node.seriesId"
+                :label="node.seriesName"
+                :value="node.seriesId"
+              ></el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item prop="personId" label="爱豆" class="search-form-item">
+            <el-select v-model="classifyData.personId" placeholder="请选择爱豆" clearable filterable>
+              <el-option v-for="person in personList" :label="person.personName" :value="person.id"></el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item prop="cardSide" label="正背面">
+            <el-select v-model="classifyData.cardSide" clearable filterable>
+              <el-option :key="1" label="正面" :value="'Front'"></el-option>
+              <el-option :key="2" label="背面" :value="'Back'"></el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item prop="cardSide" label="卡类型">
+            <el-select v-model="classifyData.cardType" clearable filterable>
+              <el-option :key="1" label="3寸小卡" :value="'3CXK'"></el-option>
+              <el-option :key="2" label="3寸拍立得" :value="'3CFP'"></el-option>
+              <el-option :key="3" label="明信片" :value="'MXP'"></el-option>
+              <el-option :key="4" label="书签" :value="'SQ'"></el-option>
+              <el-option :key="5" label="大方卡" :value="'FK'"></el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item prop="cardSide" label="年份">
+            <el-select v-model="classifyData.picYear" clearable filterable>
+              <el-option :key="1" label="2025年" :value="'2025'"></el-option>
+              <el-option :key="2" label="2024年" :value="'2024'"></el-option>
+              <el-option :key="3" label="2024年以前" :value="'2024年以前'"></el-option>
+            </el-select>
+          </el-form-item>
+        </div>
+      </el-form>
+      <span slot="footer" class="dialog-footer">
+          <el-button class="default-btn" @click="classifyVisible = false">{{$t("crud.filter.cancelBtn")}}</el-button>
+          <el-button class="default-btn primary-btn" type="primary" @click="classifySubmit()">{{$t("crud.filter.submitBtn")}}</el-button>
+        </span>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+// import AddOrUpdate from './prodTemplate-add-or-update'
+export default {
+  data () {
+    return {
+      dataList: [],
+      page: {
+        total: 0, // 总页数
+        currentPage: 1, // 当前页数
+        pageSize: 10 // 每页显示多少条
+      },
+      searchForm: {
+        templateStyleId: null,
+        templateSeriesId: null,
+        templateUsage: null
+      }, // 搜索
+      dataListLoading: false,
+      addOrUpdateVisible: false,
+      seriesList: [],
+      styleList: [],
+      usageList:[],
+      personList:[],
+      resourcesUrl: process.env.VUE_APP_RESOURCES_URL,
+      previewPicUrl: null,
+      previewPicDialogVisible: false,
+      templateUsageList:[{label:'小卡', value:'YXK'},{label:'3寸花式拍立得', value:'FP'}
+                        ,{label:'4寸花式拍立得', value:'4CFP'},{label:'5寸花式拍立得', value:'5CFP'}
+                        ,{label:'明信片', value:'MXP'},{label:'票根', value:'PG'},{label:'书签', value:'SQ'}
+                        ,{label:'竖版四宫格', value:'SBSGG'},{label:'田字四宫格', value:'TZSGG'},{label:'小方卡', value:'XFK'},
+                        {label:'3寸仿真拍立得', value:'3CFZFP'},{label:'4寸仿真拍立得', value:'4CFZFP'},{label:'5寸仿真拍立得', value:'5CFZFP'}],
+      multipleSelection: [],
+      classifyVisible: false,
+      classifyData:{}
+    }
+  },
+  components: {
+    // AddOrUpdate
+  },
+  created () {
+    this.getDataList()
+    this.getSeriesList()
+  },
+  mounted () {
+  },
+  methods: {
+    openClassifyDialog(){
+      this.classifyVisible = true
+    },
+    selectSeries(value){
+      this.personList = []
+      this.getPersonList(value)
+    },
+    classifySubmit(){
+      if(this.multipleSelection.length === 0){
+        return
+      }else{
+        this.classifyData.prodTemplateList = this.multipleSelection
+      }
+      this.$http({
+        url: this.$http.adornUrl('/prod/prodTemplate/saveBatchToCardCommonLib'),
+        method: 'post',
+        data: this.$http.adornData(this.classifyData)
+      }).then(({data}) => {
+        this.$message({
+          message: this.$i18n.t('publics.operation'),
+          type: 'success',
+          duration: 200,
+          onClose: () => {
+            this.classifyVisible = false
+          }
+        })
+      })
+    },
+    getPersonList (seriesId) {
+      this.$http({
+        url: this.$http.adornUrl('/cardLib/cardPerson/page'),
+        method: 'get',
+        params: this.$http.adornParams(
+          Object.assign({
+              size: 100,
+            seriesId: seriesId
+            },
+          )
+        )
+      }).then(({data}) => {
+        this.personList = data.records
+      })
+    },
+    handleSelectionChange(val) {
+      this.multipleSelection = val;
+    },
+    previewPic(row){
+      this.previewPicUrl = this.resourcesUrl + row.templatePic
+      this.previewPicDialogVisible = true;
+    },
+    getSeriesList () {
+      this.$http({
+        url: this.$http.adornUrl('/prod/prodTemplateSeries/page'),
+        method: 'get',
+        params: this.$http.adornParams(
+                Object.assign({
+                          size: 100,
+                          shopId: 1
+                        },
+                )
+        )
+      }).then(({data}) => {
+        this.seriesList = data.records
+      })
+    },
+    getDataList (page) {
+      this.dataListLoading = true
+      this.$http({
+        url: this.$http.adornUrl('/prod/prodTemplate/page'),
+        method: 'get',
+        params: this.$http.adornParams(
+          Object.assign({
+            current: page == null ? this.page.currentPage : page.currentPage,
+            size: page == null ? this.page.pageSize : page.pageSize,
+            shopId: 1,
+          },
+            this.searchForm
+          )
+        )
+      }).then(({data}) => {
+        this.dataList = data.records
+        this.page.total = data.total
+        this.dataListLoading = false
+      })
+    },
+    // 新增 / 修改
+    addOrUpdateHandle (id) {
+      this.addOrUpdateVisible = true
+      this.$nextTick(() => {
+        this.$refs.addOrUpdate.init(id)
+      })
+    },
+    deleteHandle (id) {
+      this.$confirm(this.$i18n.t('admin.isDeleOper') + '?', this.$i18n.t('text.tips'), {
+        confirmButtonText: this.$i18n.t('crud.filter.submitBtn'),
+        cancelButtonText: this.$i18n.t('crud.filter.cancelBtn'),
+        type: 'warning'
+      }).then(() => {
+        this.$http({
+          url: this.$http.adornUrl('/prod/prodTemplate/' + id),
+          method: 'delete',
+          data: this.$http.adornData({})
+        }).then(({ data }) => {
+          this.$message({
+            message: this.$i18n.t('publics.operation'),
+            type: 'success',
+            duration: 100,
+            onClose: () => {
+              this.refreshChange()
+            }
+          })
+        })
+      }).catch(() => { })
+    },
+    resetForm () {
+      this.searchForm = {
+        templateStyleId: null,
+        templateSeriesId: null
+      }
+    },
+    // 刷新回调
+    refreshChange () {
+      this.getDataList(this.page)
+    },
+    searchChange () {
+      // this.searchForm = params
+      this.getDataList(this.page)
+    },
+    handleSizeChange (val) {
+      this.page.pageSize = val
+      this.getDataList()
+    },
+    handleCurrentChange (val) {
+      this.page.currentPage = val
+      this.getDataList()
+    }
+  }
+}
+</script>
+<style lang="scss">
+.mod-prod-prodTemplate {
+}
+</style>

+ 103 - 0
src/views/modules/prod/prodTemplateSeries-add-or-update.vue

@@ -0,0 +1,103 @@
+<template>
+  <el-dialog
+    @close="closeDialog"
+    :title="!dataForm.seriesId ? this.$i18n.t('crud.addTitle') : this.$i18n.t('temp.modify')"
+    :close-on-click-modal="false"
+    :visible.sync="visible">
+    <el-form :model="dataForm" :rules="dataRule" ref="dataForm" @keyup.enter.native="dataFormSubmit()" label-width="80px">
+      <el-form-item label="系列名称" prop="seriesName">
+        <el-input v-model="dataForm.seriesName"></el-input>
+      </el-form-item>
+      <el-form-item label="模板用途" prop="seriesUsage">
+        <el-select v-model="usageList" clearable filterable multiple>
+          <el-option key="smallcard" label="小卡" value="smallcard,YXK,ZJXK,DBYXK,DBZJXK,YYYXK,YYZJXK"></el-option>
+          <el-option key="squarecard" label="大方卡" value="squarecard,FK"></el-option>
+          <el-option key="XFK" label="小方卡" value="XFK"></el-option>
+          <el-option key="badge" label="徽章" value="badge,HZ"></el-option>
+          <el-option key="postcard" label="明信片" value="postcard,MXP,YSZMXP"></el-option>
+          <el-option key="bookmark" label="书签" value="bookmark,SQ"></el-option>
+          <el-option key="tipscard" label="手幅" value="tipscard,SF"></el-option>
+          <el-option key="covercard" label="直拍封面" value="covercard,ZP"></el-option>
+          <el-option key="stub" label="票根" value="stub,PG"></el-option>
+          <el-option key="FP" label="3寸花式拍立得" value="FP,polaroid"></el-option>
+          <el-option key="4CFP" label="4寸花式拍立得" value="4CFP"></el-option>
+          <el-option key="5CFP" label="5寸花式拍立得" value="5CFP"></el-option>
+          <el-option key="SBSGG" label="竖版四宫格" value="SBSGG"></el-option>
+          <el-option key="TZSGG" label="田字四宫格" value="TZSGG"></el-option>
+          <el-option key="3CFZFP" label="3寸仿真拍立得" value="3CFZFP"></el-option>
+          <el-option key="4CFZFP" label="4寸仿真拍立得" value="4CFZFP"></el-option>
+          <el-option key="5CFZFP" label="5寸仿真拍立得" value="5CFZFP"></el-option>
+        </el-select>
+      </el-form-item>
+      <el-form-item label="排序" prop="seq">
+        <el-input v-model="dataForm.seq" type="number"></el-input>
+      </el-form-item>
+    </el-form>
+    <span slot="footer" class="dialog-footer">
+      <el-button class="default-btn" @click="visible = false">{{$t("crud.filter.cancelBtn")}}</el-button>
+      <el-button class="default-btn primary-btn" type="primary" @click="dataFormSubmit()">{{$t("crud.filter.submitBtn")}}</el-button>
+    </span>
+  </el-dialog>
+</template>
+
+<script>
+export default {
+  data () {
+    return {
+      visible: false,
+      dataForm: {
+        seriesId: null,
+        seriesName: null,
+        shopId: this.$store.state.user.shopId
+      },
+      usageList:[],
+      dataRule: {
+      }
+    }
+  },
+  methods: {
+    init (series) {
+      this.visible = true
+      this.$nextTick(() => {
+        this.$refs['dataForm'].resetFields()
+        if (series.seriesName) {
+          this.$http({
+            url: this.$http.adornUrl('/prod/prodTemplateSeries/info/' + series.seriesName),
+            method: 'get',
+            params: this.$http.adornParams()
+          }).then(({data}) => {
+            this.dataForm = data
+            // this.usageList = data.templateUsage.split(",")
+          })
+        }
+      })
+    },
+    // 表单提交
+    dataFormSubmit () {
+      this.$refs['dataForm'].validate((valid) => {
+        if (valid) {
+          this.dataForm.seriesUsage = this.usageList.join(",");
+          this.$http({
+            url: this.$http.adornUrl('/prod/prodTemplateSeries'),
+            method: this.dataForm.seriesId ? 'put' : 'post',
+            data: this.$http.adornData(this.dataForm)
+          }).then(({data}) => {
+            this.$message({
+              message: this.$i18n.t('publics.operation'),
+              type: 'success',
+              duration: 1500,
+              onClose: () => {
+                this.visible = false
+                this.$emit('refreshDataList')
+              }
+            })
+          })
+        }
+      })
+    },
+    closeDialog(){
+      this.dataForm = {}
+    }
+  }
+}
+</script>

+ 223 - 0
src/views/modules/prod/prodTemplateSeries.vue

@@ -0,0 +1,223 @@
+<template>
+  <div class="mod-prod-prodTemplateSeries">
+    <!-- 搜索相关区域 -->
+    <div class="search-bar">
+      <el-form :inline="true" class="search-form" ref="searchForm" :model="searchForm" label-width="auto" size="small">
+        <div class="input-row">
+          <el-form-item prop="seriesName" label="团队组合" class="search-form-item">
+            <el-select v-model="searchForm.seriesId" placeholder="请选择所属团体组合" :filterable="true" :remote="true" :clearable="true"
+                       :remote-method="getSeriesList" :loading="searchLoading">
+              <el-option v-for="series in seriesList" :label="series.seriesName" :value="series.seriesId"></el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item>
+            <div class="default-btn primary-btn" @click="searchChange(searchForm)">{{$t('crud.searchBtn')}}</div>
+            <div class="default-btn" @click="resetSearchForm('searchForm')">{{$t('shop.resetMap')}}</div>
+          </el-form-item>
+        </div>
+      </el-form>
+    </div>
+    <!-- 列表相关区域 -->
+    <div class="main-container">
+      <div class="operation-bar">
+        <div class="default-btn primary-btn" @click="addOrUpdateHandle()"
+             >{{$t("crud.addTitle")}}</div>
+      </div>
+      <div class="table-con spec-table">
+        <el-table
+          ref="specListTable"
+          :data="dataList"
+          header-cell-class-name="table-header"
+          row-class-name="table-row"
+          style="width: 100%">
+          <!-- 系列名称 -->
+          <el-table-column label="团队组合名称" prop="seriesName" align="center">
+            <template slot-scope="scope">
+              <span>{{ scope.row.seriesName}}</span>
+            </template>
+          </el-table-column>
+          <!-- 系列用途 -->
+          <el-table-column label="成员名称" prop="usageList" align="center" width="600px">
+            <template slot-scope="scope">
+              <div class="table-cell-text">{{ (scope.row.personList != null && scope.row.personList.length > 0)? scope.row.personList.join('/'): "" }}</div>
+            </template>
+          </el-table-column>
+          <el-table-column label="排序" prop="seq" align="center">
+            <template slot-scope="scope">
+              <span>{{ scope.row.seq}}</span>
+            </template>
+          </el-table-column>
+          <el-table-column align="center" fixed="right" :label="$t('publics.operating')" width="auto">
+            <template slot-scope="scope">
+              <div class="text-btn-con">
+                <div class="default-btn text-btn" @click="addOrUpdateHandle(scope.row)">{{$t("crud.updateBtn")}}</div>
+                <div class="default-btn text-btn" @click="addOrUpdatePersonHandle(scope.row)">更新成员</div>
+                <div class="default-btn text-btn" @click.stop="deleteHandle(scope.row.seriesId)">{{$t("text.delBtn")}}</div>
+                </div>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+        <el-pagination
+          v-if="dataList.length"
+          @size-change="handleSizeChange"
+          @current-change="handleCurrentChange"
+          :current-page="page.currentPage"
+          :page-sizes="[10, 20, 50, 100]"
+          :page-size="page.pageSize"
+          layout="total, sizes, prev, pager, next, jumper"
+          :total="page.total">
+        </el-pagination>
+      </div>
+    <add-or-update v-if="addOrUpdateVisible" ref="addOrUpdate" @refreshDataList="refreshChange"></add-or-update>
+    <add-or-update-person v-if="addOrUpdatePersonVisible" ref="addOrUpdatePerson" @refreshDataList="refreshChange"></add-or-update-person>
+  </div>
+</template>
+
+<script>
+import AddOrUpdate from './prodTemplateSeries-add-or-update'
+import AddOrUpdatePerson from './cardPerson-add-or-update'
+export default {
+  data () {
+    return {
+      dataList: [],
+      page: {
+        total: 0, // 总页数
+        currentPage: 1, // 当前页数
+        pageSize: 10 // 每页显示多少条
+      },
+      searchForm: {}, // 搜索
+      dataListLoading: false,
+      addOrUpdateVisible: false,
+      addOrUpdatePersonVisible: false,
+      usageList:[],
+      seriesList: [],
+      searchLoading: false,
+    }
+  },
+  components: {
+    AddOrUpdate, AddOrUpdatePerson
+  },
+  created () {
+    this.getDataList()
+  },
+  mounted () {
+  },
+  methods: {
+    // remoteQuerySeries(seriesName){
+    //   this.$http({
+    //     url: this.$http.adornUrl('/prod/prodTemplateSeries/info/' + seriesName),
+    //     method: 'get',
+    //   }).then(({data}) => {
+    //     this.seriesList = [{label: data.seriesName, value: data.seriesId}]
+    //   })
+    // },
+    getSeriesList (seriesName) {
+      this.$http({
+        url: this.$http.adornUrl('/prod/prodTemplateSeries/list'),
+        method: 'get',
+        params: this.$http.adornParams(
+          Object.assign({
+              size: 100,
+              seriesName: seriesName
+            },
+          )
+        )
+      }).then(({data}) => {
+        this.seriesList = data
+      })
+    },
+    getDataList (page) {
+      this.dataListLoading = true
+      this.$http({
+        url: this.$http.adornUrl('/prod/prodTemplateSeries/page'),
+        method: 'get',
+        params: this.$http.adornParams(
+          Object.assign({
+            current: page == null ? this.page.currentPage : page.currentPage,
+            size: page == null ? this.page.pageSize : page.pageSize,
+          },
+            this.searchForm
+          )
+        )
+      }).then(({data}) => {
+        this.dataList = data.records
+        this.dataList.forEach(item => {
+          item.personList = item.personList.map(i => {
+            return i.personName
+          })
+        })
+        this.page.total = data.total
+        this.dataListLoading = false
+        this.seriesList = this.dataList
+      })
+    },
+    // 新增 / 修改
+    addOrUpdateHandle (series) {
+      this.addOrUpdateVisible = true
+      this.$nextTick(() => {
+        this.$refs.addOrUpdate.init(series)
+      })
+    },
+    // 新增 / 修改
+     addOrUpdatePersonHandle (series) {
+      this.addOrUpdatePersonVisible = true
+      this.$nextTick(() => {
+        this.$refs.addOrUpdatePerson.init(series)
+      })
+    },
+    deleteHandle (id) {
+      this.$confirm(this.$i18n.t('admin.isDeleOper') + '?', this.$i18n.t('text.tips'), {
+        confirmButtonText: this.$i18n.t('crud.filter.submitBtn'),
+        cancelButtonText: this.$i18n.t('crud.filter.cancelBtn'),
+        type: 'warning'
+      }).then(() => {
+        this.$http({
+          url: this.$http.adornUrl('/prod/prodTemplateSeries/' + id),
+          method: 'delete',
+          data: this.$http.adornData({})
+        }).then(({ data }) => {
+          this.$message({
+            message: this.$i18n.t('publics.operation'),
+            type: 'success',
+            duration: 1500,
+            onClose: () => {
+              this.refreshChange()
+            }
+          })
+        })
+      }).catch(() => { })
+    },
+    // 刷新回调
+    refreshChange () {
+      // this.page.currentPage = 1
+      this.getDataList(this.page)
+    },
+    searchChange (params) {
+      this.page.currentPage = 1
+      this.searchForm = params
+      this.getDataList(this.page)
+    },
+    handleSizeChange (val) {
+      this.page.pageSize = val
+      this.getDataList()
+    },
+    handleCurrentChange (val) {
+      this.page.currentPage = val
+      this.getDataList()
+    },
+    /**
+     * 重置表单
+     * @param {String} formName 表单名称
+     */
+    resetSearchForm (formName) {
+      this.$refs[formName].resetFields()
+      this.getDataList()
+    }
+  }
+}
+</script>
+<style lang="scss">
+.mod-prod-prodTemplateSeries {
+}
+</style>