feat: 完善作品征集投稿和收货地址管理
- 新增移动端作品征集列表、投稿和我的作品页面 - 支持 PC 和移动端选择、新增及编辑收货地址 - 限制同一用户在同一活动、主题类型和作品类型下重复投稿 - 兼容上传接口返回的 26 位附件 ID - 统一移动端列表、表单和操作按钮样式
This commit is contained in:
@@ -25,6 +25,8 @@ public interface SysFileService extends BaseService<Sys_file> {
|
|||||||
*/
|
*/
|
||||||
String uploadReturnUrl(String engine, TempFile file);
|
String uploadReturnUrl(String engine, TempFile file);
|
||||||
|
|
||||||
|
long sizeBytes(Sys_file file);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分页
|
* 分页
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import cn.hutool.core.convert.Convert;
|
|||||||
import cn.hutool.core.date.DateUtil;
|
import cn.hutool.core.date.DateUtil;
|
||||||
import cn.hutool.core.img.ImgUtil;
|
import cn.hutool.core.img.ImgUtil;
|
||||||
import cn.hutool.core.io.FileUtil;
|
import cn.hutool.core.io.FileUtil;
|
||||||
|
import cn.hutool.json.JSONObject;
|
||||||
import cn.hutool.core.io.IoUtil;
|
import cn.hutool.core.io.IoUtil;
|
||||||
import cn.hutool.core.util.CharsetUtil;
|
import cn.hutool.core.util.CharsetUtil;
|
||||||
import cn.hutool.core.util.NumberUtil;
|
import cn.hutool.core.util.NumberUtil;
|
||||||
@@ -65,6 +66,26 @@ public class SysFileServiceImpl extends BaseServiceImpl<Sys_file> implements Sys
|
|||||||
return this.storageFile(engine, file, false);
|
return this.storageFile(engine, file, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long sizeBytes(Sys_file file) {
|
||||||
|
JSONObject metadata = file.getExtJson();
|
||||||
|
if (metadata != null && metadata.getLong("sizeBytes") != null) {
|
||||||
|
return metadata.getLong("sizeBytes");
|
||||||
|
}
|
||||||
|
if (SysFileEngineTypeEnum.LOCAL.getValue().equals(file.getEngine())) {
|
||||||
|
File storedFile = FileUtil.file(file.getStoragePath());
|
||||||
|
if (!storedFile.isFile()) {
|
||||||
|
throw new BaseException("文件不存在");
|
||||||
|
}
|
||||||
|
return storedFile.length();
|
||||||
|
}
|
||||||
|
if (SysFileEngineTypeEnum.MINIO.getValue().equals(file.getEngine())) {
|
||||||
|
String objectKey = StrUtil.removePrefix(file.getStoragePath(), "/");
|
||||||
|
return SysFileMinIoUtil.getFileSize(file.getBucket(), objectKey);
|
||||||
|
}
|
||||||
|
throw new BaseException("不支持的文件引擎");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Pagination page(Sys_file file) {
|
public Pagination page(Sys_file file) {
|
||||||
return null;
|
return null;
|
||||||
@@ -250,6 +271,7 @@ public class SysFileServiceImpl extends BaseServiceImpl<Sys_file> implements Sys
|
|||||||
sys_file.setSizeKb(Convert.toStr(NumberUtil.div(new BigDecimal(file.getSize()), BigDecimal.valueOf(1024))
|
sys_file.setSizeKb(Convert.toStr(NumberUtil.div(new BigDecimal(file.getSize()), BigDecimal.valueOf(1024))
|
||||||
.setScale(0, RoundingMode.HALF_UP)));
|
.setScale(0, RoundingMode.HALF_UP)));
|
||||||
sys_file.setSizeInfo(FileUtil.readableFileSize(file.getSize()));
|
sys_file.setSizeInfo(FileUtil.readableFileSize(file.getSize()));
|
||||||
|
sys_file.setExtJson(new JSONObject().set("sizeBytes", file.getSize()));
|
||||||
sys_file.setObjName(ObjectUtil.isNotEmpty(sys_file.getSuffix()) ? fileId + StrUtil.DOT + sys_file.getSuffix() : null);
|
sys_file.setObjName(ObjectUtil.isNotEmpty(sys_file.getSuffix()) ? fileId + StrUtil.DOT + sys_file.getSuffix() : null);
|
||||||
// 如果是图片,则压缩生成缩略图
|
// 如果是图片,则压缩生成缩略图
|
||||||
if (ObjectUtil.isNotEmpty(suffix)) {
|
if (ObjectUtil.isNotEmpty(suffix)) {
|
||||||
|
|||||||
@@ -103,6 +103,15 @@ public class SysFileMinIoUtil {
|
|||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static long getFileSize(String bucketName, String key) {
|
||||||
|
try {
|
||||||
|
initClient();
|
||||||
|
return client.statObject(StatObjectArgs.builder().bucket(bucketName).object(key).build()).size();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new BaseException("文件大小读取失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询存储桶是否存在
|
* 查询存储桶是否存在
|
||||||
* 例如:传入参数examplebucket-1250000000,返回true代表存在此桶
|
* 例如:传入参数examplebucket-1250000000,返回true代表存在此桶
|
||||||
|
|||||||
+131
@@ -0,0 +1,131 @@
|
|||||||
|
package com.budwk.app.zhgh.activity.workscollection.controller;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||||
|
import cn.dev33.satoken.annotation.SaMode;
|
||||||
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.budwk.app.base.result.Result;
|
||||||
|
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||||
|
import com.budwk.app.zhgh.welfare.model.WelfareMemberAddress;
|
||||||
|
import com.budwk.app.zhgh.welfare.service.WelfareAddressManageService;
|
||||||
|
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||||
|
import org.nutz.dao.Chain;
|
||||||
|
import org.nutz.dao.Cnd;
|
||||||
|
import org.nutz.ioc.aop.Aop;
|
||||||
|
import org.nutz.ioc.loader.annotation.Inject;
|
||||||
|
import org.nutz.ioc.loader.annotation.IocBean;
|
||||||
|
import org.nutz.mvc.annotation.At;
|
||||||
|
import org.nutz.mvc.annotation.Ok;
|
||||||
|
import org.nutz.mvc.annotation.POST;
|
||||||
|
import org.nutz.mvc.annotation.Param;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
@IocBean
|
||||||
|
@At("/platform/activity/worksCollection/addressManage")
|
||||||
|
@Ok("json:full")
|
||||||
|
public class ActivityWorksCollectionAddressController {
|
||||||
|
|
||||||
|
private static final String PERMISSION = "activity.workscollection.addressManage";
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private WelfareAddressManageService addressService;
|
||||||
|
|
||||||
|
@At("")
|
||||||
|
@Ok("beetl:/platform/zhgh/welfare/addressManage/index.html")
|
||||||
|
@SaCheckPermission(PERMISSION)
|
||||||
|
public void index() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@SaCheckPermission(value = {PERMISSION, "activity.workscollection.upload", "h5.activity.workscollection.upload"}, mode = SaMode.OR)
|
||||||
|
public Result selectUserAddress() {
|
||||||
|
return Result.success(addressService.query(currentUserAddresses().desc("isDefault")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@POST
|
||||||
|
@Aop(TransAop.READ_COMMITTED)
|
||||||
|
@SaCheckPermission(value = {PERMISSION, "activity.workscollection.upload", "h5.activity.workscollection.upload"}, mode = SaMode.OR)
|
||||||
|
public Result doSaveUserAddress(@Param("data") WelfareMemberAddress form) {
|
||||||
|
if (form == null || StrUtil.hasBlank(form.getUserName(), form.getTel(), form.getProvince(),
|
||||||
|
form.getCity(), form.getAreaCode(), form.getAddressDetail())) {
|
||||||
|
return Result.error("请填写完整的收货地址");
|
||||||
|
}
|
||||||
|
|
||||||
|
form.setTel(form.getTel().trim());
|
||||||
|
if (!form.getTel().matches("1[3-9][0-9]{9}")) {
|
||||||
|
return Result.error("请输入正确的手机号码");
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean editing = StrUtil.isNotBlank(form.getId());
|
||||||
|
Cnd condition = currentUserAddresses().and("id", "=", form.getId());
|
||||||
|
if (editing && addressService.count(condition) == 0) {
|
||||||
|
return Result.error("收货地址不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (form.isDefault()) {
|
||||||
|
addressService.dao().update(WelfareMemberAddress.class, Chain.make("isDefault", false), currentUserAddresses());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (editing) {
|
||||||
|
Chain values = Chain.make("userName", form.getUserName())
|
||||||
|
.add("tel", form.getTel())
|
||||||
|
.add("province", form.getProvince())
|
||||||
|
.add("city", form.getCity())
|
||||||
|
.add("county", form.getCounty())
|
||||||
|
.add("areaCode", form.getAreaCode())
|
||||||
|
.add("addressDetail", form.getAddressDetail())
|
||||||
|
.add("isDefault", form.isDefault())
|
||||||
|
.add("updatedBy", SecurityUtil.getUserId())
|
||||||
|
.add("updatedAt", System.currentTimeMillis());
|
||||||
|
addressService.dao().update(WelfareMemberAddress.class, values, condition);
|
||||||
|
} else {
|
||||||
|
addressService.insert(new WelfareMemberAddress()
|
||||||
|
.setUserId(SecurityUtil.getUserId())
|
||||||
|
.setUserName(form.getUserName())
|
||||||
|
.setTel(form.getTel())
|
||||||
|
.setProvince(form.getProvince())
|
||||||
|
.setCity(form.getCity())
|
||||||
|
.setCounty(form.getCounty())
|
||||||
|
.setAreaCode(form.getAreaCode())
|
||||||
|
.setAddressDetail(form.getAddressDetail())
|
||||||
|
.setDefault(form.isDefault()));
|
||||||
|
}
|
||||||
|
return Result.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@POST
|
||||||
|
@Aop(TransAop.READ_COMMITTED)
|
||||||
|
@SaCheckPermission(value = {PERMISSION, "activity.workscollection.upload", "h5.activity.workscollection.upload"}, mode = SaMode.OR)
|
||||||
|
public Result doDefault(@Param("id") String id) {
|
||||||
|
Cnd condition = currentUserAddresses().and("id", "=", id);
|
||||||
|
if (addressService.count(condition) == 0) {
|
||||||
|
return Result.error("收货地址不存在");
|
||||||
|
}
|
||||||
|
addressService.dao().update(WelfareMemberAddress.class, Chain.make("isDefault", false), currentUserAddresses());
|
||||||
|
addressService.dao().update(WelfareMemberAddress.class, Chain.make("isDefault", true), condition);
|
||||||
|
return Result.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@POST
|
||||||
|
@SaCheckPermission(value = {PERMISSION, "h5.activity.workscollection.upload"}, mode = SaMode.OR)
|
||||||
|
public Result deleteAddress(@Param("id") String id) {
|
||||||
|
int deleted = addressService.dao().clear(WelfareMemberAddress.class, currentUserAddresses().and("id", "=", id));
|
||||||
|
return deleted > 0 ? Result.success() : Result.error("收货地址不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@Ok("void")
|
||||||
|
@SaCheckPermission(PERMISSION)
|
||||||
|
public void exportAllAddress(HttpServletResponse response) {
|
||||||
|
StpUtil.checkRole("SYSADMIN");
|
||||||
|
addressService.exportAllAddress(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Cnd currentUserAddresses() {
|
||||||
|
return Cnd.where("userId", "=", SecurityUtil.getUserId());
|
||||||
|
}
|
||||||
|
}
|
||||||
+24
-2
@@ -1,6 +1,10 @@
|
|||||||
package com.budwk.app.zhgh.activity.workscollection.controller;
|
package com.budwk.app.zhgh.activity.workscollection.controller;
|
||||||
|
|
||||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||||
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
|
import com.budwk.app.base.constant.RoleConstant;
|
||||||
|
import com.budwk.app.web.commons.auth.utils.AuthUtil;
|
||||||
|
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||||
import com.budwk.app.base.result.Result;
|
import com.budwk.app.base.result.Result;
|
||||||
import com.budwk.app.zhgh.activity.workscollection.models.Activity_works_collection;
|
import com.budwk.app.zhgh.activity.workscollection.models.Activity_works_collection;
|
||||||
import com.budwk.app.zhgh.activity.workscollection.models.Activity_works_collection_upload;
|
import com.budwk.app.zhgh.activity.workscollection.models.Activity_works_collection_upload;
|
||||||
@@ -63,18 +67,36 @@ public class ActivityWorksCollectionCommonController {
|
|||||||
up.*,
|
up.*,
|
||||||
co.NAME AS activityName,
|
co.NAME AS activityName,
|
||||||
su.typeName AS subjectName,
|
su.typeName AS subjectName,
|
||||||
wo.worksTypeName AS worksName
|
wo.worksTypeName AS worksName,
|
||||||
|
CASE WHEN up.userId = @viewerId OR @readAll = 1
|
||||||
|
OR (@readUnion = 1 AND up.unionId = @viewerUnionId)
|
||||||
|
THEN address.shippingAddress END AS shippingAddress
|
||||||
FROM
|
FROM
|
||||||
`activity_works_collection_upload` up
|
`activity_works_collection_upload` up
|
||||||
LEFT JOIN activity_works_collection co ON up.activityId = co.id
|
LEFT JOIN activity_works_collection co ON up.activityId = co.id
|
||||||
LEFT JOIN activity_works_subjecttype su ON up.subjectId = su.id
|
LEFT JOIN activity_works_subjecttype su ON up.subjectId = su.id
|
||||||
LEFT JOIN activity_works_workstype wo ON up.worksId = wo.id
|
LEFT JOIN activity_works_workstype wo ON up.worksId = wo.id
|
||||||
|
LEFT JOIN (
|
||||||
|
SELECT userId,
|
||||||
|
CONCAT_WS(' ', CONCAT_WS('', province, city, county), addressDetail, userName, tel) AS shippingAddress,
|
||||||
|
ROW_NUMBER() OVER (PARTITION BY userId ORDER BY id) AS rn
|
||||||
|
FROM welfare_member_address
|
||||||
|
WHERE isDefault = 1
|
||||||
|
) address ON address.userId = up.userId AND address.rn = 1
|
||||||
$condition
|
$condition
|
||||||
""");
|
""");
|
||||||
Cnd cnd = Cnd.NEW();
|
Cnd cnd = Cnd.NEW();
|
||||||
cnd.and("up.id", "=", id);
|
cnd.and("up.id", "=", id);
|
||||||
sql.setCondition(cnd);
|
sql.setCondition(cnd);
|
||||||
NutMap result = (NutMap) Daos.query(dao, sql.toString(), Sqls.callback.map());
|
boolean canRead = StpUtil.hasPermission("activity.workscollection.read");
|
||||||
|
boolean canReadAll = canRead && AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name());
|
||||||
|
sql.setParam("viewerId", SecurityUtil.getUserId());
|
||||||
|
sql.setParam("viewerUnionId", SecurityUtil.getUnionId());
|
||||||
|
sql.setParam("readAll", canReadAll ? 1 : 0);
|
||||||
|
sql.setParam("readUnion", canRead ? 1 : 0);
|
||||||
|
sql.setCallback(Sqls.callback.map());
|
||||||
|
dao.execute(sql);
|
||||||
|
NutMap result = sql.getObject(NutMap.class);
|
||||||
return Result.success(result);
|
return Result.success(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+28
@@ -80,6 +80,9 @@ public class ActivityWorksCollectionManageController {
|
|||||||
@At
|
@At
|
||||||
@SaCheckPermission("activity.workscollection.manage")
|
@SaCheckPermission("activity.workscollection.manage")
|
||||||
public Result insert(@Param("data") @Valid Activity_works_collection worksCollection) {
|
public Result insert(@Param("data") @Valid Activity_works_collection worksCollection) {
|
||||||
|
if (!hasValidFileSizeLimits(worksCollection)) {
|
||||||
|
return Result.error("总文件大小必须大于或等于单个文件大小");
|
||||||
|
}
|
||||||
worksCollection.setIsSubmit(true);
|
worksCollection.setIsSubmit(true);
|
||||||
dao.insertWith(worksCollection, "subjectTypes");
|
dao.insertWith(worksCollection, "subjectTypes");
|
||||||
worksCollection.getSubjectTypes().forEach(item -> {
|
worksCollection.getSubjectTypes().forEach(item -> {
|
||||||
@@ -91,6 +94,9 @@ public class ActivityWorksCollectionManageController {
|
|||||||
@At
|
@At
|
||||||
@SaCheckPermission("activity.workscollection.manage")
|
@SaCheckPermission("activity.workscollection.manage")
|
||||||
public Result save(@Param("data") @Valid Activity_works_collection worksCollection) {
|
public Result save(@Param("data") @Valid Activity_works_collection worksCollection) {
|
||||||
|
if (!hasValidFileSizeLimits(worksCollection)) {
|
||||||
|
return Result.error("总文件大小必须大于或等于单个文件大小");
|
||||||
|
}
|
||||||
worksCollection.setIsSubmit(false);
|
worksCollection.setIsSubmit(false);
|
||||||
dao.insertWith(worksCollection, "subjectTypes");
|
dao.insertWith(worksCollection, "subjectTypes");
|
||||||
worksCollection.getSubjectTypes().forEach(item -> {
|
worksCollection.getSubjectTypes().forEach(item -> {
|
||||||
@@ -103,6 +109,9 @@ public class ActivityWorksCollectionManageController {
|
|||||||
@SaCheckPermission("activity.workscollection.manage")
|
@SaCheckPermission("activity.workscollection.manage")
|
||||||
@Aop(TransAop.READ_COMMITTED)
|
@Aop(TransAop.READ_COMMITTED)
|
||||||
public Result update(@Param("data") @Valid Activity_works_collection worksCollection) {
|
public Result update(@Param("data") @Valid Activity_works_collection worksCollection) {
|
||||||
|
if (!hasValidFileSizeLimits(worksCollection)) {
|
||||||
|
return Result.error("总文件大小必须大于或等于单个文件大小");
|
||||||
|
}
|
||||||
dao.update(worksCollection);
|
dao.update(worksCollection);
|
||||||
dao.updateLinks(worksCollection, "subjectTypes");
|
dao.updateLinks(worksCollection, "subjectTypes");
|
||||||
dao.insertLinks(worksCollection, "subjectTypes");
|
dao.insertLinks(worksCollection, "subjectTypes");
|
||||||
@@ -123,6 +132,25 @@ public class ActivityWorksCollectionManageController {
|
|||||||
return Result.success();
|
return Result.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean hasValidFileSizeLimits(Activity_works_collection worksCollection) {
|
||||||
|
if (worksCollection.getSubjectTypes() == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (Activity_works_subjectType subjectType : worksCollection.getSubjectTypes()) {
|
||||||
|
if (subjectType.getWorksTypes() == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (Activity_works_worksType worksType : subjectType.getWorksTypes()) {
|
||||||
|
Integer single = worksType.getAllowSingleFileSize();
|
||||||
|
Integer total = worksType.getAllowTotalFileSize();
|
||||||
|
if (single != null && single > 0 && total != null && total > 0 && total < single) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@At
|
@At
|
||||||
@SaCheckPermission("activity.workscollection.manage")
|
@SaCheckPermission("activity.workscollection.manage")
|
||||||
@Aop(TransAop.READ_COMMITTED)
|
@Aop(TransAop.READ_COMMITTED)
|
||||||
|
|||||||
+9
-1
@@ -75,12 +75,20 @@ public class ActivityWorksCollectionReadController {
|
|||||||
up.*,
|
up.*,
|
||||||
co.NAME AS activityName,
|
co.NAME AS activityName,
|
||||||
su.typeName AS subjectName,
|
su.typeName AS subjectName,
|
||||||
wo.worksTypeName AS worksName
|
wo.worksTypeName AS worksName,
|
||||||
|
address.shippingAddress
|
||||||
from
|
from
|
||||||
activity_works_collection_upload up
|
activity_works_collection_upload up
|
||||||
LEFT JOIN activity_works_collection co ON up.activityId = co.id
|
LEFT JOIN activity_works_collection co ON up.activityId = co.id
|
||||||
LEFT JOIN activity_works_subjecttype su ON up.subjectId = su.id
|
LEFT JOIN activity_works_subjecttype su ON up.subjectId = su.id
|
||||||
LEFT JOIN activity_works_workstype wo ON up.worksId = wo.id
|
LEFT JOIN activity_works_workstype wo ON up.worksId = wo.id
|
||||||
|
LEFT JOIN (
|
||||||
|
SELECT userId,
|
||||||
|
CONCAT_WS(' ', CONCAT_WS('', province, city, county), addressDetail, userName, tel) AS shippingAddress,
|
||||||
|
ROW_NUMBER() OVER (PARTITION BY userId ORDER BY id) AS rn
|
||||||
|
FROM welfare_member_address
|
||||||
|
WHERE isDefault = 1
|
||||||
|
) address ON address.userId = up.userId AND address.rn = 1
|
||||||
$condition
|
$condition
|
||||||
""");
|
""");
|
||||||
Cnd cnd = Cnd.NEW();
|
Cnd cnd = Cnd.NEW();
|
||||||
|
|||||||
+26
-52
@@ -1,22 +1,20 @@
|
|||||||
package com.budwk.app.zhgh.activity.workscollection.controller;
|
package com.budwk.app.zhgh.activity.workscollection.controller;
|
||||||
|
|
||||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||||
import com.budwk.app.base.page.Pagination;
|
|
||||||
import com.budwk.app.base.param.PageForm;
|
import com.budwk.app.base.param.PageForm;
|
||||||
import com.budwk.app.base.result.Result;
|
import com.budwk.app.base.result.Result;
|
||||||
import com.budwk.app.base.service.BaseService;
|
|
||||||
import com.budwk.app.sys.models.Sys_user;
|
|
||||||
import com.budwk.app.sys.views.View_user;
|
|
||||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||||
import com.budwk.app.zhgh.activity.basic.models.ActivityUserScope;
|
|
||||||
import com.budwk.app.zhgh.activity.workscollection.models.Activity_works_collection;
|
import com.budwk.app.zhgh.activity.workscollection.models.Activity_works_collection;
|
||||||
import com.budwk.app.zhgh.activity.workscollection.models.Activity_works_collection_upload;
|
import com.budwk.app.zhgh.activity.workscollection.models.Activity_works_collection_upload;
|
||||||
|
import com.budwk.app.zhgh.activity.workscollection.service.ActivityWorksCollectionUploadService;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import com.budwk.app.zhgh.welfare.model.WelfareMemberAddress;
|
||||||
|
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||||
|
import org.nutz.ioc.aop.Aop;
|
||||||
import org.nutz.dao.Cnd;
|
import org.nutz.dao.Cnd;
|
||||||
import org.nutz.dao.Dao;
|
import org.nutz.dao.Dao;
|
||||||
import org.nutz.dao.FieldFilter;
|
import org.nutz.dao.FieldFilter;
|
||||||
import org.nutz.dao.Sqls;
|
import org.nutz.dao.Sqls;
|
||||||
import org.nutz.dao.sql.Sql;
|
|
||||||
import org.nutz.dao.util.Daos;
|
import org.nutz.dao.util.Daos;
|
||||||
import org.nutz.dao.util.cri.SqlExpressionGroup;
|
import org.nutz.dao.util.cri.SqlExpressionGroup;
|
||||||
import org.nutz.ioc.loader.annotation.Inject;
|
import org.nutz.ioc.loader.annotation.Inject;
|
||||||
@@ -40,7 +38,7 @@ public class ActivityWorksCollectionUploadController {
|
|||||||
private Dao dao;
|
private Dao dao;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private BaseService baseService;
|
private ActivityWorksCollectionUploadService uploadService;
|
||||||
|
|
||||||
@At("")
|
@At("")
|
||||||
@Ok("beetl:/platform/zhgh/activity/workscollection/upload/index.html")
|
@Ok("beetl:/platform/zhgh/activity/workscollection/upload/index.html")
|
||||||
@@ -57,27 +55,7 @@ public class ActivityWorksCollectionUploadController {
|
|||||||
@At
|
@At
|
||||||
@SaCheckPermission("activity.workscollection.upload")
|
@SaCheckPermission("activity.workscollection.upload")
|
||||||
public Result pageData(@Valid PageForm pageForm, String activityId, String subjectId, String worksId) {
|
public Result pageData(@Valid PageForm pageForm, String activityId, String subjectId, String worksId) {
|
||||||
Sql sql = Sqls.create("""
|
return uploadService.pageData(pageForm, activityId, subjectId, worksId);
|
||||||
select
|
|
||||||
up.*,
|
|
||||||
co.NAME AS activityName,
|
|
||||||
su.typeName AS subjectName,
|
|
||||||
wo.worksTypeName AS worksName
|
|
||||||
from
|
|
||||||
activity_works_collection_upload up
|
|
||||||
LEFT JOIN activity_works_collection co ON up.activityId = co.id
|
|
||||||
LEFT JOIN activity_works_subjecttype su ON up.subjectId = su.id
|
|
||||||
LEFT JOIN activity_works_workstype wo ON up.worksId = wo.id
|
|
||||||
$condition
|
|
||||||
""");
|
|
||||||
Cnd cnd = Cnd.NEW();
|
|
||||||
cnd.and("userId", "=", SecurityUtil.getUserId());
|
|
||||||
cnd.andEX("up.activityId", "=", activityId);
|
|
||||||
cnd.andEX("up.subjectId", "=", subjectId);
|
|
||||||
cnd.andEX("up.worksId", "=", worksId);
|
|
||||||
sql.setCondition(cnd);
|
|
||||||
Pagination pagination = baseService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
|
|
||||||
return Result.success(pagination);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -87,37 +65,33 @@ public class ActivityWorksCollectionUploadController {
|
|||||||
*/
|
*/
|
||||||
@At
|
@At
|
||||||
@SaCheckPermission("activity.workscollection.upload")
|
@SaCheckPermission("activity.workscollection.upload")
|
||||||
public Result insert(@Param("data") @Valid Activity_works_collection_upload upload) {
|
@Aop(TransAop.READ_COMMITTED)
|
||||||
String activityId = upload.getActivityId();
|
public Result insert(@Param("data") @Valid Activity_works_collection_upload upload, @Param("addressId") String addressId) {
|
||||||
Activity_works_collection activity = dao.fetch(Activity_works_collection.class, activityId);
|
WelfareMemberAddress address = uploadService.shippingAddress(addressId);
|
||||||
if (activity.getActivityGroupId() != null) {
|
if (address == null) {
|
||||||
int count = dao.count(ActivityUserScope.class, Cnd.where(ActivityUserScope::getGroupId, "=", activity.getActivityGroupId())
|
return Result.error("请选择手机号有效的收货地址");
|
||||||
.and(ActivityUserScope::getUserId, "=", SecurityUtil.getUserId()));
|
|
||||||
if (count == 0) {
|
|
||||||
return Result.error("您没有权限参与该活动");
|
|
||||||
}
|
}
|
||||||
|
Result result = uploadService.insert(upload);
|
||||||
|
if (result.isSuccess()) {
|
||||||
|
uploadService.confirmShippingAddress(address);
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
View_user vwUser = dao.fetch(View_user.class, Cnd.where(View_user::getId, "=", SecurityUtil.getUserId()));
|
|
||||||
|
|
||||||
upload.setUserId(SecurityUtil.getUserId());
|
|
||||||
upload.setUserName(SecurityUtil.getUserUsername());
|
|
||||||
upload.setLoginName(SecurityUtil.getUserLoginname());
|
|
||||||
upload.setUnitId(SecurityUtil.getUnitId());
|
|
||||||
upload.setUnitName(vwUser.getUnitName());
|
|
||||||
upload.setUnionId(SecurityUtil.getUnionId());
|
|
||||||
upload.setUnionName(vwUser.getUnionName());
|
|
||||||
|
|
||||||
dao.insert(upload);
|
|
||||||
return Result.success();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@At
|
@At
|
||||||
@SaCheckPermission("activity.workscollection.upload")
|
@SaCheckPermission("activity.workscollection.upload")
|
||||||
public Result update(@Param("data") @Valid Activity_works_collection_upload upload) {
|
@Aop(TransAop.READ_COMMITTED)
|
||||||
dao.updateIgnoreNull(upload);
|
public Result update(@Param("data") @Valid Activity_works_collection_upload upload, @Param("addressId") String addressId) {
|
||||||
return Result.success();
|
WelfareMemberAddress address = uploadService.shippingAddress(addressId);
|
||||||
|
if (address == null) {
|
||||||
|
return Result.error("请选择手机号有效的收货地址");
|
||||||
|
}
|
||||||
|
Result result = uploadService.update(upload);
|
||||||
|
if (result.isSuccess()) {
|
||||||
|
uploadService.confirmShippingAddress(address);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@At
|
@At
|
||||||
|
|||||||
+196
-4
@@ -1,9 +1,33 @@
|
|||||||
package com.budwk.app.zhgh.activity.workscollection.controller.h5;
|
package com.budwk.app.zhgh.activity.workscollection.controller.h5;
|
||||||
|
|
||||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||||
|
import com.budwk.app.base.param.PageForm;
|
||||||
|
import com.budwk.app.base.result.Result;
|
||||||
|
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||||
|
import com.budwk.app.zhgh.activity.workscollection.models.Activity_works_collection;
|
||||||
|
import com.budwk.app.zhgh.activity.workscollection.models.Activity_works_collection_upload;
|
||||||
|
import com.budwk.app.zhgh.activity.workscollection.models.Activity_works_subjectType;
|
||||||
|
import com.budwk.app.zhgh.activity.workscollection.models.Activity_works_worksType;
|
||||||
|
import com.budwk.app.zhgh.activity.workscollection.service.ActivityWorksCollectionUploadService;
|
||||||
|
import com.budwk.app.zhgh.welfare.model.WelfareMemberAddress;
|
||||||
|
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||||
|
import org.nutz.ioc.aop.Aop;
|
||||||
|
import org.nutz.dao.Cnd;
|
||||||
|
import org.nutz.dao.Dao;
|
||||||
|
import org.nutz.dao.Sqls;
|
||||||
|
import org.nutz.dao.sql.Sql;
|
||||||
|
import org.nutz.ioc.loader.annotation.Inject;
|
||||||
import org.nutz.ioc.loader.annotation.IocBean;
|
import org.nutz.ioc.loader.annotation.IocBean;
|
||||||
|
import org.nutz.lang.Strings;
|
||||||
|
import org.nutz.lang.util.NutMap;
|
||||||
import org.nutz.mvc.annotation.At;
|
import org.nutz.mvc.annotation.At;
|
||||||
import org.nutz.mvc.annotation.Ok;
|
import org.nutz.mvc.annotation.Ok;
|
||||||
|
import org.nutz.mvc.annotation.POST;
|
||||||
|
import org.nutz.mvc.annotation.Param;
|
||||||
|
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 手机端作品征集
|
* 手机端作品征集
|
||||||
@@ -13,12 +37,18 @@ import org.nutz.mvc.annotation.Ok;
|
|||||||
@Ok("json:full")
|
@Ok("json:full")
|
||||||
public class H5ActivityWorksCollectionController {
|
public class H5ActivityWorksCollectionController {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private Dao dao;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private ActivityWorksCollectionUploadService uploadService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 活动列表页面
|
* 活动列表页面
|
||||||
*/
|
*/
|
||||||
@At("/activity")
|
@At({"", "/activity"})
|
||||||
@Ok("beetl:/platform/zhghh5/activity/workscollection/activity/index.html")
|
@Ok("beetl:/platform/zhghh5/activity/workscollection/activity/index.html")
|
||||||
@SaCheckPermission("activity.workscollection.upload")
|
@SaCheckPermission("h5.activity.workscollection.upload")
|
||||||
public void activity() {
|
public void activity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,7 +57,7 @@ public class H5ActivityWorksCollectionController {
|
|||||||
*/
|
*/
|
||||||
@At("/upload")
|
@At("/upload")
|
||||||
@Ok("beetl:/platform/zhghh5/activity/workscollection/upload/index.html")
|
@Ok("beetl:/platform/zhghh5/activity/workscollection/upload/index.html")
|
||||||
@SaCheckPermission("activity.workscollection.upload")
|
@SaCheckPermission("h5.activity.workscollection.upload")
|
||||||
public void upload() {
|
public void upload() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,7 +66,169 @@ public class H5ActivityWorksCollectionController {
|
|||||||
*/
|
*/
|
||||||
@At("/upload/mine")
|
@At("/upload/mine")
|
||||||
@Ok("beetl:/platform/zhghh5/activity/workscollection/upload/mine.html")
|
@Ok("beetl:/platform/zhghh5/activity/workscollection/upload/mine.html")
|
||||||
@SaCheckPermission("activity.workscollection.upload")
|
@SaCheckPermission("h5.activity.workscollection.upload")
|
||||||
public void uploadMine() {
|
public void uploadMine() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@At("/upload/address")
|
||||||
|
@Ok("beetl:/platform/zhghh5/activity/workscollection/upload/address.html")
|
||||||
|
@SaCheckPermission("h5.activity.workscollection.upload")
|
||||||
|
public void uploadAddress() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@At("/upload/address/edit")
|
||||||
|
@Ok("beetl:/platform/zhghh5/activity/workscollection/upload/addressEdit.html")
|
||||||
|
@SaCheckPermission("h5.activity.workscollection.upload")
|
||||||
|
public void editUploadAddress() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@At("/activities")
|
||||||
|
@POST
|
||||||
|
@SaCheckPermission("h5.activity.workscollection.upload")
|
||||||
|
public Result activities() {
|
||||||
|
Date now = new Date();
|
||||||
|
List<NutMap> activities = dao.query(Activity_works_collection.class,
|
||||||
|
visibleActivities().desc("startDateTime").desc("id")).stream()
|
||||||
|
.map(activity -> activityInfo(activity, now))
|
||||||
|
.toList();
|
||||||
|
return Result.success(activities);
|
||||||
|
}
|
||||||
|
|
||||||
|
@At("/activityDetail")
|
||||||
|
@POST
|
||||||
|
@SaCheckPermission("h5.activity.workscollection.upload")
|
||||||
|
public Result activityDetail(@Param("activityId") String activityId) {
|
||||||
|
Activity_works_collection activity = findActivity(activityId);
|
||||||
|
if (activity == null) {
|
||||||
|
return Result.error("活动不存在或您没有权限参与该活动");
|
||||||
|
}
|
||||||
|
List<Activity_works_subjectType> subjects = dao.query(Activity_works_subjectType.class,
|
||||||
|
Cnd.where("activityId", "=", activityId).asc("location"));
|
||||||
|
for (Activity_works_subjectType subject : subjects) {
|
||||||
|
subject.setWorksTypes(dao.query(Activity_works_worksType.class,
|
||||||
|
Cnd.where("subjectId", "=", subject.getId()).asc("location")));
|
||||||
|
}
|
||||||
|
return Result.success(activityInfo(activity, new Date())
|
||||||
|
.setv("content", activity.getContent())
|
||||||
|
.setv("introduce", activity.getIntroduce())
|
||||||
|
.setv("rewardMethod", activity.getRewardMethod())
|
||||||
|
.setv("subjectTypes", subjects));
|
||||||
|
}
|
||||||
|
|
||||||
|
@At("/minePageData")
|
||||||
|
@POST
|
||||||
|
@SaCheckPermission("h5.activity.workscollection.upload")
|
||||||
|
public Result minePageData(@Valid PageForm pageForm) {
|
||||||
|
return uploadService.pageData(pageForm, null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@At("/myWork")
|
||||||
|
@POST
|
||||||
|
@SaCheckPermission("h5.activity.workscollection.upload")
|
||||||
|
public Result myWork(@Param("id") String id) {
|
||||||
|
Activity_works_collection_upload work = dao.fetch(Activity_works_collection_upload.class, myWorkCondition(id));
|
||||||
|
return work == null ? Result.error("作品不存在") : Result.success(work);
|
||||||
|
}
|
||||||
|
|
||||||
|
@At("/saveWork")
|
||||||
|
@POST
|
||||||
|
@SaCheckPermission("h5.activity.workscollection.upload")
|
||||||
|
@Aop(TransAop.READ_COMMITTED)
|
||||||
|
public Result saveWork(@Param("data") @Valid Activity_works_collection_upload form, @Param("addressId") String addressId) {
|
||||||
|
WelfareMemberAddress address = uploadService.shippingAddress(addressId);
|
||||||
|
if (address == null) {
|
||||||
|
return Result.error("请选择手机号有效的收货地址");
|
||||||
|
}
|
||||||
|
String id = form.getId();
|
||||||
|
Activity_works_collection_upload original = null;
|
||||||
|
if (Strings.isNotBlank(id)) {
|
||||||
|
original = dao.fetch(Activity_works_collection_upload.class, myWorkCondition(id));
|
||||||
|
if (original == null) {
|
||||||
|
return Result.error("作品不存在");
|
||||||
|
}
|
||||||
|
if (!original.getActivityId().equals(form.getActivityId())) {
|
||||||
|
return Result.error("无法变更作品所属活动");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Activity_works_collection activity = findActivity(form.getActivityId());
|
||||||
|
if (activity == null) {
|
||||||
|
return Result.error("活动不存在或您没有权限参与该活动");
|
||||||
|
}
|
||||||
|
if (!"open".equals(activityStatus(activity, new Date()))) {
|
||||||
|
return Result.error("当前活动不在作品提交时间内");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Activity_works_collection_upload work = new Activity_works_collection_upload();
|
||||||
|
work.setActivityId(activity.getId());
|
||||||
|
work.setSubjectId(form.getSubjectId());
|
||||||
|
work.setWorksId(form.getWorksId());
|
||||||
|
work.setName(form.getName());
|
||||||
|
work.setDescription(form.getDescription());
|
||||||
|
work.setFiles(form.getFiles());
|
||||||
|
Result result;
|
||||||
|
if (original == null) {
|
||||||
|
result = uploadService.insert(work);
|
||||||
|
} else {
|
||||||
|
work.setId(original.getId());
|
||||||
|
result = uploadService.update(work);
|
||||||
|
}
|
||||||
|
if (result.isSuccess()) {
|
||||||
|
uploadService.confirmShippingAddress(address);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@At("/deleteWork")
|
||||||
|
@POST
|
||||||
|
@SaCheckPermission("h5.activity.workscollection.upload")
|
||||||
|
public Result deleteWork(@Param("id") String id) {
|
||||||
|
Activity_works_collection_upload work = dao.fetch(Activity_works_collection_upload.class, myWorkCondition(id));
|
||||||
|
if (work == null) {
|
||||||
|
return Result.error("作品不存在");
|
||||||
|
}
|
||||||
|
Sql openActivity = Sqls.create("""
|
||||||
|
SELECT id FROM activity_works_collection
|
||||||
|
WHERE id = @activityId AND enable = 1 AND (isSubmit = 1 OR isSubmit IS NULL)
|
||||||
|
AND startDateTime <= CURRENT_TIMESTAMP(3) AND endDateTime >= CURRENT_TIMESTAMP(3)
|
||||||
|
""").setParam("activityId", work.getActivityId());
|
||||||
|
return dao.clear(Activity_works_collection_upload.class, myWorkCondition(id).and("activityId", "in", openActivity)) > 0
|
||||||
|
? Result.success() : Result.error("当前活动不在作品提交时间内,无法删除作品");
|
||||||
|
}
|
||||||
|
|
||||||
|
private Cnd visibleActivities() {
|
||||||
|
return Cnd.where("enable", "=", true)
|
||||||
|
.and(Cnd.exps("isSubmit", "=", true).or("isSubmit", "is", null))
|
||||||
|
.and(Cnd.exps("activityGroupId", "is", null)
|
||||||
|
.or("activityGroupId", "in", Sqls.create("select groupId from activity_user_scope where userId = @userId")
|
||||||
|
.setParam("userId", SecurityUtil.getUserId())));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Activity_works_collection findActivity(String activityId) {
|
||||||
|
return dao.fetch(Activity_works_collection.class, visibleActivities().and("id", "=", activityId));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Cnd myWorkCondition(String id) {
|
||||||
|
return Cnd.where("id", "=", id).and("userId", "=", SecurityUtil.getUserId());
|
||||||
|
}
|
||||||
|
|
||||||
|
private NutMap activityInfo(Activity_works_collection activity, Date now) {
|
||||||
|
return NutMap.NEW()
|
||||||
|
.setv("id", activity.getId())
|
||||||
|
.setv("name", activity.getName())
|
||||||
|
.setv("cover", activity.getCover())
|
||||||
|
.setv("startDateTime", activity.getStartDateTime() == null ? null : activity.getStartDateTime().getTime())
|
||||||
|
.setv("endDateTime", activity.getEndDateTime() == null ? null : activity.getEndDateTime().getTime())
|
||||||
|
.setv("status", activityStatus(activity, now));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String activityStatus(Activity_works_collection activity, Date now) {
|
||||||
|
if (activity.getStartDateTime() == null || activity.getEndDateTime() == null || now.after(activity.getEndDateTime())) {
|
||||||
|
return "closed";
|
||||||
|
}
|
||||||
|
return now.before(activity.getStartDateTime()) ? "upcoming" : "open";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+265
@@ -0,0 +1,265 @@
|
|||||||
|
package com.budwk.app.zhgh.activity.workscollection.service;
|
||||||
|
|
||||||
|
import cn.hutool.json.JSONObject;
|
||||||
|
import com.budwk.app.base.page.Pagination;
|
||||||
|
import com.budwk.app.sys.models.Sys_file;
|
||||||
|
import com.budwk.app.sys.services.SysFileService;
|
||||||
|
import com.budwk.app.zhgh.activity.workscollection.models.Activity_works_subjectType;
|
||||||
|
import com.budwk.app.zhgh.activity.workscollection.models.Activity_works_worksType;
|
||||||
|
import com.budwk.app.base.param.PageForm;
|
||||||
|
import com.budwk.app.base.result.Result;
|
||||||
|
import com.budwk.app.base.service.BaseService;
|
||||||
|
import com.budwk.app.sys.views.View_user;
|
||||||
|
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||||
|
import com.budwk.app.zhgh.activity.basic.models.ActivityUserScope;
|
||||||
|
import com.budwk.app.zhgh.activity.workscollection.models.Activity_works_collection;
|
||||||
|
import com.budwk.app.zhgh.activity.workscollection.models.Activity_works_collection_upload;
|
||||||
|
import com.budwk.app.zhgh.welfare.model.WelfareMemberAddress;
|
||||||
|
import org.nutz.dao.Chain;
|
||||||
|
import org.nutz.dao.Cnd;
|
||||||
|
import org.nutz.dao.Dao;
|
||||||
|
import org.nutz.dao.Sqls;
|
||||||
|
import org.nutz.dao.sql.Sql;
|
||||||
|
import org.nutz.ioc.loader.annotation.Inject;
|
||||||
|
import org.nutz.ioc.loader.annotation.IocBean;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
@IocBean
|
||||||
|
public class ActivityWorksCollectionUploadService {
|
||||||
|
|
||||||
|
private static final String DUPLICATE_SUBMISSION = "您已提交过该活动下此主题类型和作品类型的作品,请在我的作品中编辑。";
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private Dao dao;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private SysFileService sysFileService;
|
||||||
|
|
||||||
|
private static final String DOWNLOAD_PREFIX = "/platform/sys/file/download?id=";
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private BaseService baseService;
|
||||||
|
|
||||||
|
public Result pageData(PageForm pageForm, String activityId, String subjectId, String worksId) {
|
||||||
|
Sql sql = Sqls.create("""
|
||||||
|
select
|
||||||
|
up.*,
|
||||||
|
co.NAME AS activityName,
|
||||||
|
co.cover AS activityCover,
|
||||||
|
CASE WHEN co.enable = 1 AND (co.isSubmit = 1 OR co.isSubmit IS NULL)
|
||||||
|
AND co.startDateTime <= CURRENT_TIMESTAMP(3)
|
||||||
|
AND co.endDateTime >= CURRENT_TIMESTAMP(3)
|
||||||
|
THEN 1 ELSE 0 END AS canModify,
|
||||||
|
su.typeName AS subjectName,
|
||||||
|
wo.worksTypeName AS worksName,
|
||||||
|
address.shippingAddress
|
||||||
|
from
|
||||||
|
activity_works_collection_upload up
|
||||||
|
LEFT JOIN activity_works_collection co ON up.activityId = co.id
|
||||||
|
LEFT JOIN activity_works_subjecttype su ON up.subjectId = su.id
|
||||||
|
LEFT JOIN activity_works_workstype wo ON up.worksId = wo.id
|
||||||
|
LEFT JOIN (
|
||||||
|
SELECT userId,
|
||||||
|
CONCAT_WS(' ', CONCAT_WS('', province, city, county), addressDetail, userName, tel) AS shippingAddress,
|
||||||
|
ROW_NUMBER() OVER (PARTITION BY userId ORDER BY id) AS rn
|
||||||
|
FROM welfare_member_address
|
||||||
|
WHERE isDefault = 1
|
||||||
|
) address ON address.userId = up.userId AND address.rn = 1
|
||||||
|
$condition
|
||||||
|
""");
|
||||||
|
Cnd cnd = Cnd.NEW();
|
||||||
|
cnd.and("up.userId", "=", SecurityUtil.getUserId());
|
||||||
|
cnd.andEX("up.activityId", "=", activityId);
|
||||||
|
cnd.andEX("up.subjectId", "=", subjectId);
|
||||||
|
cnd.andEX("up.worksId", "=", worksId);
|
||||||
|
cnd.desc("up.createdAt").desc("up.id");
|
||||||
|
sql.setCondition(cnd);
|
||||||
|
Pagination pagination = baseService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
|
||||||
|
return Result.success(pagination);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WelfareMemberAddress shippingAddress(String addressId) {
|
||||||
|
if (addressId == null || addressId.isBlank()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
WelfareMemberAddress address = dao.fetch(WelfareMemberAddress.class,
|
||||||
|
Cnd.where("userId", "=", SecurityUtil.getUserId()).and("id", "=", addressId));
|
||||||
|
return address != null && address.getTel() != null && address.getTel().matches("1[3-9][0-9]{9}")
|
||||||
|
? address : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void confirmShippingAddress(WelfareMemberAddress address) {
|
||||||
|
dao.update(WelfareMemberAddress.class, Chain.make("isDefault", false),
|
||||||
|
Cnd.where("userId", "=", address.getUserId()).and("id", "<>", address.getId()));
|
||||||
|
dao.update(WelfareMemberAddress.class, Chain.make("isDefault", true),
|
||||||
|
Cnd.where("userId", "=", address.getUserId()).and("id", "=", address.getId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Result insert(Activity_works_collection_upload upload) {
|
||||||
|
String userId = SecurityUtil.getUserId();
|
||||||
|
String activityId = upload.getActivityId();
|
||||||
|
Activity_works_collection activity = dao.fetch(Activity_works_collection.class, activityId);
|
||||||
|
if (activity == null) {
|
||||||
|
return Result.error("活动不存在");
|
||||||
|
}
|
||||||
|
if (activity.getActivityGroupId() != null) {
|
||||||
|
int count = dao.count(ActivityUserScope.class, Cnd.where(ActivityUserScope::getGroupId, "=", activity.getActivityGroupId())
|
||||||
|
.and(ActivityUserScope::getUserId, "=", userId));
|
||||||
|
if (count == 0) {
|
||||||
|
return Result.error("您没有权限参与该活动");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!lockSubmitter(userId)) {
|
||||||
|
return Result.error("投稿用户不存在");
|
||||||
|
}
|
||||||
|
if (dao.count(Activity_works_collection_upload.class, submissionCondition(userId, upload)) > 0) {
|
||||||
|
return Result.error(DUPLICATE_SUBMISSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result validation = validateWork(upload, null);
|
||||||
|
if (!validation.isSuccess()) {
|
||||||
|
return validation;
|
||||||
|
}
|
||||||
|
|
||||||
|
View_user vwUser = dao.fetch(View_user.class, Cnd.where(View_user::getId, "=", userId));
|
||||||
|
|
||||||
|
upload.setUserId(userId);
|
||||||
|
upload.setUserName(SecurityUtil.getUserUsername());
|
||||||
|
upload.setLoginName(SecurityUtil.getUserLoginname());
|
||||||
|
upload.setUnitId(SecurityUtil.getUnitId());
|
||||||
|
upload.setUnitName(vwUser.getUnitName());
|
||||||
|
upload.setUnionId(SecurityUtil.getUnionId());
|
||||||
|
upload.setUnionName(vwUser.getUnionName());
|
||||||
|
|
||||||
|
dao.insert(upload);
|
||||||
|
return Result.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Result update(Activity_works_collection_upload upload) {
|
||||||
|
String userId = SecurityUtil.getUserId();
|
||||||
|
if (!lockSubmitter(userId)) {
|
||||||
|
return Result.error("投稿用户不存在");
|
||||||
|
}
|
||||||
|
Activity_works_collection_upload original = dao.fetch(Activity_works_collection_upload.class,
|
||||||
|
Cnd.where("id", "=", upload.getId()).and("userId", "=", userId));
|
||||||
|
if (original == null) {
|
||||||
|
return Result.error("作品不存在");
|
||||||
|
}
|
||||||
|
if (upload.getActivityId() == null) {
|
||||||
|
upload.setActivityId(original.getActivityId());
|
||||||
|
}
|
||||||
|
boolean sameCategory = Objects.equals(original.getActivityId(), upload.getActivityId())
|
||||||
|
&& Objects.equals(original.getSubjectId(), upload.getSubjectId())
|
||||||
|
&& Objects.equals(original.getWorksId(), upload.getWorksId());
|
||||||
|
if (!sameCategory && dao.count(Activity_works_collection_upload.class,
|
||||||
|
submissionCondition(userId, upload).and("id", "<>", original.getId())) > 0) {
|
||||||
|
return Result.error(DUPLICATE_SUBMISSION);
|
||||||
|
}
|
||||||
|
Result validation = validateWork(upload, original);
|
||||||
|
if (!validation.isSuccess()) {
|
||||||
|
return validation;
|
||||||
|
}
|
||||||
|
upload.setUserId(userId);
|
||||||
|
return dao.updateIgnoreNull(upload) > 0 ? Result.success() : Result.error("作品不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
private Result validateWork(Activity_works_collection_upload form, Activity_works_collection_upload original) {
|
||||||
|
Activity_works_subjectType subject = dao.fetch(Activity_works_subjectType.class,
|
||||||
|
Cnd.where("id", "=", form.getSubjectId()).and("activityId", "=", form.getActivityId()));
|
||||||
|
Activity_works_worksType worksType = dao.fetch(Activity_works_worksType.class,
|
||||||
|
Cnd.where("id", "=", form.getWorksId()).and("subjectId", "=", form.getSubjectId()));
|
||||||
|
if (subject == null || worksType == null) {
|
||||||
|
return Result.error("请选择该活动下有效的主题类型和作品类型");
|
||||||
|
}
|
||||||
|
if (overLimit(worksType.getMaxWordCount(), form.getDescription().length())) {
|
||||||
|
return Result.error("作品描述超过该作品类型的字数限制");
|
||||||
|
}
|
||||||
|
if (overLimit(worksType.getAllowFileNum(), form.getFiles().size())) {
|
||||||
|
return Result.error("附件数量超过该作品类型的限制");
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<String> existingUrls = new HashSet<>();
|
||||||
|
if (original != null && original.getFiles() != null) {
|
||||||
|
for (JSONObject file : original.getFiles()) {
|
||||||
|
existingUrls.add(attachmentUrl(file));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Set<String> fileIds = new HashSet<>();
|
||||||
|
List<JSONObject> files = new ArrayList<>();
|
||||||
|
long totalSizeBytes = 0;
|
||||||
|
for (JSONObject attachment : form.getFiles()) {
|
||||||
|
String url = attachmentUrl(attachment);
|
||||||
|
if (url == null || !url.startsWith(DOWNLOAD_PREFIX)) {
|
||||||
|
return Result.error("请上传有效的作品附件");
|
||||||
|
}
|
||||||
|
String fileId = url.substring(DOWNLOAD_PREFIX.length());
|
||||||
|
if (!fileId.matches("[a-zA-Z0-9]{26}(?:[a-zA-Z0-9]{6})?") || !fileIds.add(fileId)) {
|
||||||
|
return Result.error("作品附件无效或重复");
|
||||||
|
}
|
||||||
|
Sys_file file = dao.fetch(Sys_file.class, fileId);
|
||||||
|
if (file == null || Boolean.TRUE.equals(file.getDelFlag())
|
||||||
|
|| !(SecurityUtil.getUserId().equals(file.getCreatedBy()) || existingUrls.contains(url))) {
|
||||||
|
return Result.error("请上传有效的作品附件");
|
||||||
|
}
|
||||||
|
List<String> allowedTypes = worksType.getAllowFileTypes();
|
||||||
|
if (allowedTypes != null && !allowedTypes.isEmpty()
|
||||||
|
&& allowedTypes.stream().noneMatch(type -> type.equalsIgnoreCase(file.getSuffix()))) {
|
||||||
|
return Result.error("附件格式不符合该作品类型的要求");
|
||||||
|
}
|
||||||
|
long sizeBytes;
|
||||||
|
try {
|
||||||
|
sizeBytes = sysFileService.sizeBytes(file);
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
return Result.error("无法读取作品附件大小,请重新上传");
|
||||||
|
}
|
||||||
|
if (sizeBytes < 0 || exceedsFileSize(worksType.getAllowSingleFileSize(), sizeBytes)) {
|
||||||
|
return Result.error("单个附件大小超过该作品类型的限制");
|
||||||
|
}
|
||||||
|
totalSizeBytes += sizeBytes;
|
||||||
|
files.add(new JSONObject()
|
||||||
|
.set("name", file.getName())
|
||||||
|
.set("url", url)
|
||||||
|
.set("size", sizeBytes)
|
||||||
|
.set("response", new JSONObject().set("code", 0).set("data", url)));
|
||||||
|
}
|
||||||
|
if (exceedsFileSize(worksType.getAllowTotalFileSize(), totalSizeBytes)) {
|
||||||
|
return Result.error("附件总大小超过该作品类型的限制");
|
||||||
|
}
|
||||||
|
form.setFiles(files);
|
||||||
|
return Result.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean exceedsFileSize(Integer limitKb, long sizeBytes) {
|
||||||
|
return limitKb != null && limitKb > 0 && sizeBytes > limitKb * 1024L;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean overLimit(Integer limit, long value) {
|
||||||
|
return limit != null && limit > 0 && value > limit;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String attachmentUrl(JSONObject file) {
|
||||||
|
JSONObject response = file == null ? null : file.getJSONObject("response");
|
||||||
|
return response == null ? null : response.getStr("data");
|
||||||
|
}
|
||||||
|
|
||||||
|
private Cnd submissionCondition(String userId, Activity_works_collection_upload upload) {
|
||||||
|
return Cnd.where("userId", "=", userId)
|
||||||
|
.and("activityId", "=", upload.getActivityId())
|
||||||
|
.and("subjectId", "=", upload.getSubjectId())
|
||||||
|
.and("worksId", "=", upload.getWorksId());
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean lockSubmitter(String userId) {
|
||||||
|
// 在投稿事务中锁定账号行,串行处理同一用户从不同端发起的保存请求。
|
||||||
|
Sql sql = Sqls.create("SELECT id FROM sys_user WHERE id = @userId FOR UPDATE");
|
||||||
|
sql.setParam("userId", userId);
|
||||||
|
sql.setCallback(Sqls.callback.str());
|
||||||
|
return dao.execute(sql).getResult() != null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
INSERT INTO sys_menu (id, parentId, path, name, aliasName, type, href, target, icon, showit, disabled, permission, note, location, hasChildren, createdBy, createdAt, updatedBy, updatedAt, delFlag, processKey, platform, moduleId, isQuickEntry) VALUES ('85bd177d04154c4c8eb57d6e6cd16893', '', '0172', '作品征集', null, 'menu', '/platform/h5/activity/worksCollection/activity', null, '/platform/sys/file/download?id=7hf45bajvmjg2on1tb6b6dhhl0', 1, 0, 'h5.activity.workscollection.upload', null, 17, 0, '17a7f8ad3ee947b4a26175049a9c253d', 1794556127700, '17a7f8ad3ee947b4a26175049a9c253d', 1794556139027, 0, null, 'H5', '543c7a3c6fde4a01a89570b4479c93f4', 0);
|
||||||
|
INSERT INTO sys_menu (id, parentId, path, name, aliasName, type, href, target, icon, showit, disabled, permission, note, location, hasChildren, createdBy, createdAt, updatedBy, updatedAt, delFlag, processKey, platform, moduleId, isQuickEntry) VALUES ('9fcbf730b6a94b709b4cccec598b25a6', '91d79e0f4e464f298e7a6b37217386d3', '000900010004', '收货地址', null, 'menu', '/platform/activity/worksCollection/addressManage', null, null, 1, 0, 'activity.workscollection.addressManage', null, 22, 0, '17a7f8ad3ee947b4a26175049a9c253d', 1794557773073, '17a7f8ad3ee947b4a26175049a9c253d', 1794557773074, 0, null, 'PC', '889c6f60d1ca474494c4573f0b289c72', 0);
|
||||||
|
INSERT INTO sys_role_menu (roleId, menuId) VALUES ('7f4a820d5a394bb8a0a92d6699afe7c8', '85bd177d04154c4c8eb57d6e6cd16893');
|
||||||
|
INSERT INTO sys_role_menu (roleId, menuId) VALUES ('7f4a820d5a394bb8a0a92d6699afe7c8', '9fcbf730b6a94b709b4cccec598b25a6');
|
||||||
@@ -154,6 +154,10 @@ module.exports = {
|
|||||||
required: false
|
required: false
|
||||||
},
|
},
|
||||||
// 接受上传的文件类型
|
// 接受上传的文件类型
|
||||||
|
validate_file: {
|
||||||
|
type: Function,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
accept: {
|
accept: {
|
||||||
type: String,
|
type: String,
|
||||||
default: "",
|
default: "",
|
||||||
@@ -290,6 +294,9 @@ module.exports = {
|
|||||||
|
|
||||||
// 这是兜底逻辑,保准只让这个image类型上传图片
|
// 这是兜底逻辑,保准只让这个image类型上传图片
|
||||||
beforeUpload(file) {
|
beforeUpload(file) {
|
||||||
|
if (this.validate_file) {
|
||||||
|
return this.validate_file(file, this.fileList)
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
|
|
||||||
// if (!this.fileAccept || typeof this.fileAccept !== "string") {
|
// if (!this.fileAccept || typeof this.fileAccept !== "string") {
|
||||||
@@ -546,9 +553,13 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$message.success("获取手机文件成功")
|
const newFileList = [...originFileList]
|
||||||
|
for (const file of data.files) {
|
||||||
|
if (this.validate_file && !this.validate_file(file, newFileList)) return
|
||||||
|
newFileList.push(file)
|
||||||
|
}
|
||||||
|
|
||||||
const newFileList = originFileList.concat(data.files)
|
this.$message.success("获取手机文件成功")
|
||||||
this.$emit("update:value", newFileList)
|
this.$emit("update:value", newFileList)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ const AU_INFO_TEMPLATE = {
|
|||||||
<el-descriptions-item label="主题类型">{{viewData.subjectName}}</el-descriptions-item>
|
<el-descriptions-item label="主题类型">{{viewData.subjectName}}</el-descriptions-item>
|
||||||
<el-descriptions-item label="作品类型" :span="2">{{viewData.worksName}}</el-descriptions-item>
|
<el-descriptions-item label="作品类型" :span="2">{{viewData.worksName}}</el-descriptions-item>
|
||||||
<el-descriptions-item label="作品描述" :span="3">{{viewData.description}}</el-descriptions-item>
|
<el-descriptions-item label="作品描述" :span="3">{{viewData.description}}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="收货地址" :span="3">{{viewData.shippingAddress || '—'}}</el-descriptions-item>
|
||||||
<el-descriptions-item label="作品附件" :span="3">
|
<el-descriptions-item label="作品附件" :span="3">
|
||||||
<template slot="label">作品附件</template>
|
<template slot="label">作品附件</template>
|
||||||
<file-preview complete_result :files="viewData.files"></file-preview>
|
<file-preview complete_result :files="viewData.files"></file-preview>
|
||||||
|
|||||||
@@ -107,12 +107,14 @@ layout("/layouts/platform.html"){
|
|||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<el-form-item label="主题类型" prop="subjectTypes">
|
<template v-for="(type,index) in formData.subjectTypes">
|
||||||
<el-row class="pb5" v-for="(type,index) in formData.subjectTypes" :key="type.id">
|
<el-form-item :key="'subject-' + (type.id || index)" label="主题类型"
|
||||||
<el-col :span="20">
|
:prop="index === 0 ? 'subjectTypes' : undefined">
|
||||||
<el-input placeholder="请输入名称" v-model="type.typeName"></el-input>
|
<el-row>
|
||||||
|
<el-col :span="18">
|
||||||
|
<el-input placeholder="请输入主题类型" v-model="type.typeName"></el-input>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="2" style="text-align: center">
|
<el-col :span="2" :offset="2" style="text-align: center">
|
||||||
<el-button @click="addType(index)" icon="el-icon-plus" type="primary"></el-button>
|
<el-button @click="addType(index)" icon="el-icon-plus" type="primary"></el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="2" style="text-align: center">
|
<el-col :span="2" style="text-align: center">
|
||||||
@@ -123,16 +125,12 @@ layout("/layouts/platform.html"){
|
|||||||
type="danger"
|
type="danger"
|
||||||
></el-button>
|
></el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col class="pt5 pb5">
|
</el-row>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item v-if="type.worksTypes.length" :key="'works-' + (type.id || index)" label="作品类型">
|
||||||
<el-row class="pb5" v-for="(worksType,worksIndex) in type.worksTypes" :key="worksType.id">
|
<el-row class="pb5" v-for="(worksType,worksIndex) in type.worksTypes" :key="worksType.id">
|
||||||
<el-col :span="18">
|
<el-col :span="18">
|
||||||
<el-col :span="4">
|
<el-input placeholder="请输入作品类型" v-model="worksType.worksTypeName"></el-input>
|
||||||
<span class="el-form-item__label" v-if="worksIndex === 0">作品类型</span>
|
|
||||||
<span v-else> </span>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="20">
|
|
||||||
<el-input placeholder="请输入名称" v-model="worksType.worksTypeName"></el-input>
|
|
||||||
</el-col>
|
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="2" style="text-align: center">
|
<el-col :span="2" style="text-align: center">
|
||||||
<el-button @click="openSetting(worksType)" icon="el-icon-s-tools"
|
<el-button @click="openSetting(worksType)" icon="el-icon-s-tools"
|
||||||
@@ -147,9 +145,8 @@ layout("/layouts/platform.html"){
|
|||||||
type="danger"></el-button>
|
type="danger"></el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</template>
|
||||||
<el-form-item label="面向对象" prop="joinCnd">
|
<el-form-item label="面向对象" prop="joinCnd">
|
||||||
<div style="display: flex; justify-content: space-between">
|
<div style="display: flex; justify-content: space-between">
|
||||||
<div style="width: 99%">
|
<div style="width: 99%">
|
||||||
@@ -213,7 +210,8 @@ layout("/layouts/platform.html"){
|
|||||||
<el-dialog :close-on-click-modal="false" :visible.sync="settingDialogVisible" title="更多设置" top="4%" width="40%">
|
<el-dialog :close-on-click-modal="false" :visible.sync="settingDialogVisible" title="更多设置" top="4%" width="40%">
|
||||||
<el-form :model="currentWorksType" label-width="160px" size="small">
|
<el-form :model="currentWorksType" label-width="160px" size="small">
|
||||||
<el-form-item label="作品介绍最多字数">
|
<el-form-item label="作品介绍最多字数">
|
||||||
<el-input-number :max="10000" :min="1" style="width: 100%"
|
<el-input-number :max="100" :min="1" :precision="0" style="width: 100%"
|
||||||
|
placeholder="请输入作品介绍最多字数"
|
||||||
v-model="currentWorksType.maxWordCount"></el-input-number>
|
v-model="currentWorksType.maxWordCount"></el-input-number>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
@@ -233,17 +231,20 @@ layout("/layouts/platform.html"){
|
|||||||
|
|
||||||
<el-form-item label="允许上传的文件数量" prop="allowFileNum">
|
<el-form-item label="允许上传的文件数量" prop="allowFileNum">
|
||||||
<el-input-number :max="10000" :min="1" style="width: 100%"
|
<el-input-number :max="10000" :min="1" style="width: 100%"
|
||||||
v-model="currentWorksType.allowFileNum"></el-input-number>
|
placeholder="请输入允许上传的文件数量"
|
||||||
|
v-model="currentWorksType.allowFileNum" :precision="0"></el-input-number>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="单个文件大小(kb)" prop="allowSingleFileSize">
|
<el-form-item label="单个文件大小(kb)" prop="allowSingleFileSize">
|
||||||
<el-input-number :min="1" style="width: 100%"
|
<el-input-number :min="1" style="width: 100%"
|
||||||
v-model="currentWorksType.allowSingleFileSize"></el-input-number>
|
placeholder="请输入单个文件大小上限(KB)"
|
||||||
|
v-model="currentWorksType.allowSingleFileSize" :precision="0"></el-input-number>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="总文件大小(kb)" prop="allowTotalFileSize">
|
<el-form-item label="总文件大小(kb)" prop="allowTotalFileSize">
|
||||||
<el-input-number :min="1" style="width: 100%"
|
<el-input-number :min="1" style="width: 100%"
|
||||||
v-model="currentWorksType.allowTotalFileSize"></el-input-number>
|
placeholder="请输入文件总大小上限(KB)"
|
||||||
|
v-model="currentWorksType.allowTotalFileSize" :precision="0"></el-input-number>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<!-- <div class="left-span-label">上传图片设置</div>-->
|
<!-- <div class="left-span-label">上传图片设置</div>-->
|
||||||
@@ -301,7 +302,7 @@ layout("/layouts/platform.html"){
|
|||||||
|
|
||||||
<el-row class="mt20" justify="end" type="flex">
|
<el-row class="mt20" justify="end" type="flex">
|
||||||
<el-button @click="settingDialogVisible=false">取消</el-button>
|
<el-button @click="settingDialogVisible=false">取消</el-button>
|
||||||
<el-button @click="settingDialogVisible = false" type="primary">确定</el-button>
|
<el-button @click="applyWorksTypeSettings" type="primary">确定</el-button>
|
||||||
</el-row>
|
</el-row>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
@@ -325,6 +326,7 @@ layout("/layouts/platform.html"){
|
|||||||
allowFileTypes: [],
|
allowFileTypes: [],
|
||||||
},
|
},
|
||||||
settingDialogVisible: false,
|
settingDialogVisible: false,
|
||||||
|
editingWorksType: null,
|
||||||
colorList: ["#081776", "#31cab1", "#e54242", "#ff8939", "#ffb712", "#1dc47b", "#4495f7", "#ff5e8b", "#5d6e7f"],
|
colorList: ["#081776", "#31cab1", "#e54242", "#ff8939", "#ffb712", "#1dc47b", "#4495f7", "#ff5e8b", "#5d6e7f"],
|
||||||
pageForm: {
|
pageForm: {
|
||||||
activityTime: []
|
activityTime: []
|
||||||
@@ -354,9 +356,30 @@ layout("/layouts/platform.html"){
|
|||||||
this.formData.subjectTypes.splice(index + 1, 0, {worksTypes: [item]})
|
this.formData.subjectTypes.splice(index + 1, 0, {worksTypes: [item]})
|
||||||
},
|
},
|
||||||
openSetting(worksType) {
|
openSetting(worksType) {
|
||||||
this.currentWorksType = worksType
|
this.editingWorksType = worksType
|
||||||
|
this.currentWorksType = { ...worksType, allowFileTypes: [...(worksType.allowFileTypes || [])] }
|
||||||
this.settingDialogVisible = true
|
this.settingDialogVisible = true
|
||||||
},
|
},
|
||||||
|
applyWorksTypeSettings() {
|
||||||
|
if (!this.validateFileSizeLimits(this.currentWorksType)) return
|
||||||
|
Object.keys(this.currentWorksType).forEach(key => {
|
||||||
|
this.$set(this.editingWorksType, key, this.currentWorksType[key])
|
||||||
|
})
|
||||||
|
this.settingDialogVisible = false
|
||||||
|
},
|
||||||
|
validateFileSizeLimits(worksType) {
|
||||||
|
const { allowSingleFileSize, allowTotalFileSize } = worksType
|
||||||
|
if (allowSingleFileSize > 0 && allowTotalFileSize > 0 && allowTotalFileSize < allowSingleFileSize) {
|
||||||
|
const name = worksType.worksTypeName
|
||||||
|
this.$message.warning((name ? "「" + name + "」:" : "") + "总文件大小必须大于或等于单个文件大小")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
validateWorksTypeSettings() {
|
||||||
|
return (this.formData.subjectTypes || []).every(subject =>
|
||||||
|
(subject.worksTypes || []).every(worksType => this.validateFileSizeLimits(worksType)))
|
||||||
|
},
|
||||||
addWorksType(type, worksIndex) {
|
addWorksType(type, worksIndex) {
|
||||||
let item = {}
|
let item = {}
|
||||||
this.initData(item)
|
this.initData(item)
|
||||||
@@ -405,13 +428,16 @@ layout("/layouts/platform.html"){
|
|||||||
this.$refs.guava.index()
|
this.$refs.guava.index()
|
||||||
},
|
},
|
||||||
doSubmit() {
|
doSubmit() {
|
||||||
|
if (!this.validateWorksTypeSettings()) return
|
||||||
this.$refs.formRef.validate((valid) => {
|
this.$refs.formRef.validate((valid) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
this.formData.startDateTime = this.formData.activityTime[0]
|
this.formData.startDateTime = this.formData.activityTime[0]
|
||||||
this.formData.endDateTime = this.formData.activityTime[1]
|
this.formData.endDateTime = this.formData.activityTime[1]
|
||||||
this.formData.nbStartDateTime = this.formData.nbTime[0]
|
const [nbStartDateTime = null, nbEndDateTime = null] = this.formData.nbTime || []
|
||||||
this.formData.nbEndDateTime = this.formData.nbTime[1]
|
this.formData.nbStartDateTime = nbStartDateTime
|
||||||
|
this.formData.nbEndDateTime = nbEndDateTime
|
||||||
this.formData.type = "1"
|
this.formData.type = "1"
|
||||||
|
this.formData.isSubmit = true
|
||||||
let loading = this.$loading({
|
let loading = this.$loading({
|
||||||
lock: true,
|
lock: true,
|
||||||
text: "数据正在提交中,请稍后...",
|
text: "数据正在提交中,请稍后...",
|
||||||
@@ -432,11 +458,14 @@ layout("/layouts/platform.html"){
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
doSave() {
|
doSave() {
|
||||||
|
if (!this.validateWorksTypeSettings()) return
|
||||||
this.formData.startDateTime = this.formData.activityTime[0]
|
this.formData.startDateTime = this.formData.activityTime[0]
|
||||||
this.formData.endDateTime = this.formData.activityTime[1]
|
this.formData.endDateTime = this.formData.activityTime[1]
|
||||||
this.formData.nbStartDateTime = this.formData.nbTime[0]
|
const [nbStartDateTime = null, nbEndDateTime = null] = this.formData.nbTime || []
|
||||||
this.formData.nbEndDateTime = this.formData.nbTime[1]
|
this.formData.nbStartDateTime = nbStartDateTime
|
||||||
|
this.formData.nbEndDateTime = nbEndDateTime
|
||||||
this.formData.type = "1"
|
this.formData.type = "1"
|
||||||
|
this.formData.isSubmit = false
|
||||||
let loading = this.$loading({
|
let loading = this.$loading({
|
||||||
lock: true,
|
lock: true,
|
||||||
text: "数据正在保存中,请稍后...",
|
text: "数据正在保存中,请稍后...",
|
||||||
|
|||||||
@@ -62,6 +62,9 @@ layout("/layouts/platform.html"){
|
|||||||
<el-table-column label="工号" prop="loginName"></el-table-column>
|
<el-table-column label="工号" prop="loginName"></el-table-column>
|
||||||
<el-table-column label="单位" prop="unitName"></el-table-column>
|
<el-table-column label="单位" prop="unitName"></el-table-column>
|
||||||
<el-table-column label="分工会" prop="unionName"></el-table-column>
|
<el-table-column label="分工会" prop="unionName"></el-table-column>
|
||||||
|
<el-table-column label="收货地址" prop="shippingAddress" min-width="240" show-overflow-tooltip>
|
||||||
|
<template slot-scope="{row}">{{row.shippingAddress || '—'}}</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column label="上传时间" prop="createdAt">
|
<el-table-column label="上传时间" prop="createdAt">
|
||||||
<template scope="scope">
|
<template scope="scope">
|
||||||
<span>{{$moment(scope.row.createdAt).format( 'YYYY-MM-DD')}}</span>
|
<span>{{$moment(scope.row.createdAt).format( 'YYYY-MM-DD')}}</span>
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
const AU_FORM_TEMPLATE = {
|
const AU_FORM_TEMPLATE = {
|
||||||
template: /*language=HTML*/ `
|
template: /*language=HTML*/ `
|
||||||
|
<div>
|
||||||
<el-dialog :title="formData.id ? '编辑':'新增'" :visible.sync="dialogFormVisible" width="60%"
|
<el-dialog :title="formData.id ? '编辑':'新增'" :visible.sync="dialogFormVisible" width="60%"
|
||||||
:close-on-click-modal="false">
|
:close-on-click-modal="false">
|
||||||
<el-form :model="formData" ref="formRef" size="small" label-width="80px" :rules="formRules">
|
<el-form :model="formData" ref="formRef" size="small" label-width="80px" :rules="formRules">
|
||||||
<el-form-item label="活动主题" prop="activityId">
|
<el-form-item label="活动主题" prop="activityId">
|
||||||
<el-select clearable placeholder="请输入内容" v-model="formData.activityId" @change="activityChange"
|
<el-select clearable placeholder="请输入内容" v-model="formData.activityId" @change="changeActivity"
|
||||||
style="width: 100%">
|
style="width: 100%">
|
||||||
<el-option v-for="item in activityOptions" :key="item.id" :label="item.name"
|
<el-option v-for="item in activityOptions" :key="item.id" :label="item.name"
|
||||||
:value="item.id"></el-option>
|
:value="item.id"></el-option>
|
||||||
@@ -12,7 +13,7 @@ const AU_FORM_TEMPLATE = {
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="主题类型" prop="subjectId">
|
<el-form-item label="主题类型" prop="subjectId">
|
||||||
<el-select clearable placeholder="请选择主题类型" v-model="formData.subjectId"
|
<el-select clearable placeholder="请选择主题类型" v-model="formData.subjectId"
|
||||||
@change="subjectChange" style="width: 100%">
|
@change="changeSubject" style="width: 100%">
|
||||||
<el-option v-for="item in subjectTypesOptions" :key="item.id" :label="item.typeName"
|
<el-option v-for="item in subjectTypesOptions" :key="item.id" :label="item.typeName"
|
||||||
:value="item.id"></el-option>
|
:value="item.id"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
@@ -28,9 +29,19 @@ const AU_FORM_TEMPLATE = {
|
|||||||
<el-input v-model="formData.name" clearable placeholder="请输入作品名称"></el-input>
|
<el-input v-model="formData.name" clearable placeholder="请输入作品名称"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="作品描述" prop="description">
|
<el-form-item label="作品描述" prop="description">
|
||||||
<el-input v-model="formData.description" type="textarea" :autosize="{ minRows: 2, maxRows: 4}"
|
<el-input v-model="formData.description" :maxlength="descriptionLimit" show-word-limit type="textarea" :autosize="{ minRows: 2, maxRows: 4}"
|
||||||
clearable placeholder="请输入作品描述"></el-input>
|
clearable placeholder="请输入作品描述"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item label="收货地址" required>
|
||||||
|
<el-select :value="shippingAddress ? shippingAddress.id : ''" placeholder="请选择收货地址"
|
||||||
|
:disabled="submitting" :loading="addressLoading" style="width: 100%" @change="changeShippingAddress">
|
||||||
|
<el-option v-for="row in addressOptions" :key="row.id" :label="addressText(row)"
|
||||||
|
:value="row.id" :disabled="!validPhone(row.tel)"></el-option>
|
||||||
|
<el-option label="管理收货地址" value="manage">
|
||||||
|
<span style="color: #409eff"><i class="el-icon-setting"></i> 管理收货地址</span>
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
<el-form-item label="附件" prop="files">
|
<el-form-item label="附件" prop="files">
|
||||||
<file-upload
|
<file-upload
|
||||||
:value.sync="formData.files"
|
:value.sync="formData.files"
|
||||||
@@ -39,19 +50,29 @@ const AU_FORM_TEMPLATE = {
|
|||||||
upload_result_category="array"
|
upload_result_category="array"
|
||||||
complete_result
|
complete_result
|
||||||
:accept="fileAccept"
|
:accept="fileAccept"
|
||||||
|
:validate_file="validateUploadFile"
|
||||||
></file-upload>
|
></file-upload>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<div slot="footer" class="dialog-footer">
|
<div slot="footer" class="dialog-footer">
|
||||||
<el-button @click="dialogFormVisible = false">取 消</el-button>
|
<el-button @click="dialogFormVisible = false">取 消</el-button>
|
||||||
<el-button type="primary" @click="doSubmit">提 交</el-button>
|
<el-button type="primary" :loading="submitting" @click="doSubmit">提 交</el-button>
|
||||||
</div>
|
</div>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
<shipping-address ref="shippingAddress" @selected="shippingAddress = $event"
|
||||||
|
@addresses-updated="refreshShippingAddress"></shipping-address>
|
||||||
|
</div>
|
||||||
`,
|
`,
|
||||||
|
components: { "shipping-address": WORKS_SHIPPING_ADDRESS },
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
dialogFormVisible: false,
|
dialogFormVisible: false,
|
||||||
formData: {},
|
formData: {},
|
||||||
|
shippingAddress: null,
|
||||||
|
addressOptions: [],
|
||||||
|
addressLoading: false,
|
||||||
|
addressRequest: 0,
|
||||||
|
submitting: false,
|
||||||
formRules: {
|
formRules: {
|
||||||
activityId: [{ required: true, message: "必填", trigger: ["change", "blur"] }],
|
activityId: [{ required: true, message: "必填", trigger: ["change", "blur"] }],
|
||||||
subjectId: [{ required: true, message: "必填", trigger: ["change", "blur"] }],
|
subjectId: [{ required: true, message: "必填", trigger: ["change", "blur"] }],
|
||||||
@@ -65,25 +86,94 @@ const AU_FORM_TEMPLATE = {
|
|||||||
worksTypeOptions: [],
|
worksTypeOptions: [],
|
||||||
|
|
||||||
chooseWorksType: {},
|
chooseWorksType: {},
|
||||||
upload_text: "",
|
|
||||||
fileAccept: null
|
fileAccept: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {},
|
computed: {
|
||||||
|
descriptionLimit() {
|
||||||
|
const limit = this.chooseWorksType.maxWordCount
|
||||||
|
return limit > 0 ? Math.min(limit, 100) : 100
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
worksTypeChange(val) {
|
worksTypeChange(val) {
|
||||||
this.chooseWorksType = this.worksTypeOptions.find((o) => o.id === val)
|
this.chooseWorksType = this.worksTypeOptions.find(option => option.id === val) || {}
|
||||||
this.fileUploadNum = this.chooseWorksType.allowFileNum
|
this.fileAccept = (this.chooseWorksType.allowFileTypes || []).map(type => "." + type).join(",")
|
||||||
if (this.chooseWorksType.allowFileTypes && this.chooseWorksType.allowFileTypes.length > 0) {
|
},
|
||||||
const allowFileTypes = this.chooseWorksType.allowFileTypes.join(",")
|
attachmentError(files) {
|
||||||
this.upload_text = "请上传<span style='color: red'>" + allowFileTypes + "</span>格式的文件"
|
const type = this.chooseWorksType
|
||||||
this.fileAccept = this.chooseWorksType.allowFileTypes.map((item) => "." + item).join(",")
|
const extensions = (type.allowFileTypes || []).map(value => value.toLowerCase())
|
||||||
|
if (type.allowFileNum > 0 && files.length > type.allowFileNum) {
|
||||||
|
return "最多只能上传 " + type.allowFileNum + " 个附件"
|
||||||
|
}
|
||||||
|
let totalBytes = 0
|
||||||
|
for (const file of files) {
|
||||||
|
const name = file.name || ""
|
||||||
|
const extension = name.includes(".") ? name.split(".").pop().toLowerCase() : ""
|
||||||
|
if (extensions.length && !extensions.includes(extension)) {
|
||||||
|
return "附件格式不符合要求,可上传 " + extensions.join("、")
|
||||||
|
}
|
||||||
|
const size = Number(file.size) || 0
|
||||||
|
if (type.allowSingleFileSize > 0 && size > type.allowSingleFileSize * 1024) {
|
||||||
|
return "单个附件不能超过 " + type.allowSingleFileSize + " KB"
|
||||||
|
}
|
||||||
|
totalBytes += size
|
||||||
|
}
|
||||||
|
if (type.allowTotalFileSize > 0 && totalBytes > type.allowTotalFileSize * 1024) {
|
||||||
|
return "附件总大小不能超过 " + type.allowTotalFileSize + " KB"
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
},
|
||||||
|
validateUploadFile(file, files) {
|
||||||
|
if (!this.formData.worksId) {
|
||||||
|
this.$message.warning("请先选择作品类型")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
const error = this.attachmentError([...files.filter(item => file.uid == null || item.uid !== file.uid), file])
|
||||||
|
if (error) this.$message.warning(error)
|
||||||
|
return !error
|
||||||
|
},
|
||||||
|
addressText(row) {
|
||||||
|
return [row.userName, row.tel, [row.province, row.city, row.county, row.addressDetail].filter(Boolean).join("")].filter(Boolean).join(" ")
|
||||||
|
},
|
||||||
|
validPhone(value) {
|
||||||
|
return /^1[3-9][0-9]{9}$/.test(value)
|
||||||
|
},
|
||||||
|
changeShippingAddress(id) {
|
||||||
|
if (id === "manage") {
|
||||||
|
this.$refs.shippingAddress.open(this.shippingAddress)
|
||||||
} else {
|
} else {
|
||||||
this.upload_text = ""
|
this.shippingAddress = this.addressOptions.find(row => row.id === id) || null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
refreshShippingAddress(addresses) {
|
||||||
|
this.addressRequest++
|
||||||
|
this.addressLoading = false
|
||||||
|
this.addressOptions = addresses
|
||||||
|
if (this.shippingAddress) {
|
||||||
|
this.shippingAddress = addresses.find(row => row.id === this.shippingAddress.id) || null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async loadAddressOptions(request) {
|
||||||
|
this.addressLoading = true
|
||||||
|
try {
|
||||||
|
const { data } = await this.$axios.post("/platform/activity/worksCollection/addressManage/selectUserAddress")
|
||||||
|
if (request === this.addressRequest) {
|
||||||
|
this.addressOptions = data
|
||||||
|
this.shippingAddress = data.find(row => row.isDefault && this.validPhone(row.tel)) || null
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// 地址选择弹窗可重新加载地址。
|
||||||
|
} finally {
|
||||||
|
if (request === this.addressRequest) this.addressLoading = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onOpen(id) {
|
onOpen(id) {
|
||||||
|
this.shippingAddress = null
|
||||||
|
this.addressOptions = []
|
||||||
|
this.loadAddressOptions(++this.addressRequest)
|
||||||
this.dialogFormVisible = true
|
this.dialogFormVisible = true
|
||||||
|
this.worksTypeChange(null)
|
||||||
if (id) {
|
if (id) {
|
||||||
this.$axios.post(loc() + "/findOne", { id }).then(async (res) => {
|
this.$axios.post(loc() + "/findOne", { id }).then(async (res) => {
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
@@ -113,21 +203,20 @@ const AU_FORM_TEMPLATE = {
|
|||||||
// }
|
// }
|
||||||
// },
|
// },
|
||||||
doSubmit() {
|
doSubmit() {
|
||||||
// if (
|
if (this.submitting) return
|
||||||
// this.formData.files &&
|
if (!this.shippingAddress || !this.validPhone(this.shippingAddress.tel)) {
|
||||||
// this.formData.files.length > 0 &&
|
this.$message.warning("请选择手机号有效的收货地址")
|
||||||
// this.chooseWorksType.allowFileTypes &&
|
return
|
||||||
// this.chooseWorksType.allowFileTypes.length > 0
|
}
|
||||||
// ) {
|
if ((this.formData.description || "").length > this.descriptionLimit) {
|
||||||
// for (let i = 1; i <= this.formData.files.length; i++) {
|
this.$message.warning("作品描述最多 " + this.descriptionLimit + " 个字")
|
||||||
// const file = this.formData.files[i - 1]
|
return
|
||||||
// const suffixName = this.getFileExtension(file.name)
|
}
|
||||||
// if (!this.chooseWorksType.allowFileTypes.includes(suffixName)) {
|
const attachmentError = this.attachmentError(this.formData.files || [])
|
||||||
// this.$message.warning("此次活动不支持上传" + suffixName + "格式的文件")
|
if (attachmentError) {
|
||||||
// return
|
this.$message.warning(attachmentError)
|
||||||
// }
|
return
|
||||||
// }
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
this.$confirm("您确定要提交吗?", "提示", {
|
this.$confirm("您确定要提交吗?", "提示", {
|
||||||
confirmButtonText: "确定",
|
confirmButtonText: "确定",
|
||||||
@@ -136,12 +225,20 @@ const AU_FORM_TEMPLATE = {
|
|||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.$refs.formRef.validate((valid) => {
|
this.$refs.formRef.validate((valid) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
this.$axios.post(loc() + (this.formData.id ? "/update" : "/insert"), { data: JSON.stringify(this.formData) }).then((res) => {
|
const editing = !!this.formData.id
|
||||||
|
if (this.submitting) return
|
||||||
|
this.submitting = true
|
||||||
|
this.$axios.post(loc() + (editing ? "/update" : "/insert"), {
|
||||||
|
data: JSON.stringify(this.formData),
|
||||||
|
addressId: this.shippingAddress.id
|
||||||
|
}).then((res) => {
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
this.dialogFormVisible = false
|
this.dialogFormVisible = false
|
||||||
this.$message.success(res.msg)
|
this.$message.success(res.msg)
|
||||||
this.$emit("refresh")
|
this.$emit("refresh")
|
||||||
}
|
}
|
||||||
|
}).finally(() => {
|
||||||
|
this.submitting = false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -155,16 +252,28 @@ const AU_FORM_TEMPLATE = {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
changeActivity(value) {
|
||||||
|
this.$set(this.formData, "subjectId", null)
|
||||||
|
this.changeSubject(null)
|
||||||
|
this.subjectTypesOptions = []
|
||||||
|
if (value) this.activityChange(value)
|
||||||
|
},
|
||||||
|
changeSubject(value) {
|
||||||
|
this.$set(this.formData, "worksId", null)
|
||||||
|
this.worksTypeOptions = []
|
||||||
|
this.worksTypeChange(null)
|
||||||
|
if (value) this.subjectChange(value)
|
||||||
|
},
|
||||||
activityChange(value) {
|
activityChange(value) {
|
||||||
this.$axios.post("/platform/activity/worksCollection/common/getSubjectTypes", { activityId: value }).then((res) => {
|
this.$axios.post("/platform/activity/worksCollection/common/getSubjectTypes", { activityId: value }).then((res) => {
|
||||||
if (res.code === 0) {
|
if (res.code === 0 && this.formData.activityId === value) {
|
||||||
this.subjectTypesOptions = res.data
|
this.subjectTypesOptions = res.data
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
async subjectChange(value) {
|
async subjectChange(value) {
|
||||||
const resp = await this.$axios.post("/platform/activity/worksCollection/common/getWorksTypes", { subjectId: value })
|
const resp = await this.$axios.post("/platform/activity/worksCollection/common/getWorksTypes", { subjectId: value })
|
||||||
if (resp.code === 0) {
|
if (resp.code === 0 && this.formData.subjectId === value) {
|
||||||
this.worksTypeOptions = resp.data
|
this.worksTypeOptions = resp.data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,6 +47,9 @@ layout("/layouts/platform.html"){
|
|||||||
<el-table-column label="工号" prop="loginName"></el-table-column>
|
<el-table-column label="工号" prop="loginName"></el-table-column>
|
||||||
<el-table-column label="单位" prop="unitName"></el-table-column>
|
<el-table-column label="单位" prop="unitName"></el-table-column>
|
||||||
<el-table-column label="分工会" prop="unionName"></el-table-column>
|
<el-table-column label="分工会" prop="unionName"></el-table-column>
|
||||||
|
<el-table-column label="收货地址" prop="shippingAddress" min-width="240" show-overflow-tooltip>
|
||||||
|
<template slot-scope="{row}">{{row.shippingAddress || '—'}}</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column label="上传时间" prop="createdAt">
|
<el-table-column label="上传时间" prop="createdAt">
|
||||||
<template scope="scope">
|
<template scope="scope">
|
||||||
<span>{{$moment(scope.row.createdAt).format('YYYY-MM-DD')}}</span>
|
<span>{{$moment(scope.row.createdAt).format('YYYY-MM-DD')}}</span>
|
||||||
@@ -69,6 +72,7 @@ layout("/layouts/platform.html"){
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
<!--#include("shippingAddress.js"){}#-->
|
||||||
<!--#include("auForm.js"){}#-->
|
<!--#include("auForm.js"){}#-->
|
||||||
<!--#include("../common/info.js"){}#-->
|
<!--#include("../common/info.js"){}#-->
|
||||||
new Vue({
|
new Vue({
|
||||||
|
|||||||
+98
@@ -0,0 +1,98 @@
|
|||||||
|
<!--#include("/platform/zhgh/welfare/addressManage/addressDialog.js"){}#-->
|
||||||
|
const WORKS_SHIPPING_ADDRESS = {
|
||||||
|
template: /*language=HTML*/ `
|
||||||
|
<div>
|
||||||
|
<el-dialog title="选择收货地址" :visible.sync="visible" width="580px" append-to-body
|
||||||
|
:close-on-click-modal="false">
|
||||||
|
<div style="display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 16px">
|
||||||
|
<p style="margin: 0; color: #606266">请选择活动纪念品的收货地址。</p>
|
||||||
|
<el-button type="primary" size="small" :disabled="loading" @click="addAddress">新增地址</el-button>
|
||||||
|
</div>
|
||||||
|
<div v-loading="loading">
|
||||||
|
<el-radio-group v-if="addresses.length" v-model="selectedId" style="display: grid; gap: 10px; max-height: 45vh; overflow-y: auto">
|
||||||
|
<div v-for="row in addresses" :key="row.id" @click="selectedId = row.id"
|
||||||
|
:style="{ borderColor: selectedId === row.id ? '#409eff' : '#dcdfe6' }"
|
||||||
|
style="padding: 12px; border: 1px solid; border-radius: 6px; cursor: pointer">
|
||||||
|
<div style="display: flex; align-items: center; justify-content: space-between; gap: 8px">
|
||||||
|
<el-radio :label="row.id">
|
||||||
|
{{ row.userName }} {{ row.tel }}
|
||||||
|
<el-tag v-if="row.isDefault" size="mini">默认</el-tag>
|
||||||
|
</el-radio>
|
||||||
|
<el-button type="text" icon="el-icon-edit" title="编辑地址" aria-label="编辑地址"
|
||||||
|
:disabled="loading" @click.stop="editAddress(row)"></el-button>
|
||||||
|
</div>
|
||||||
|
<div style="padding: 4px 0 0 24px; overflow-wrap: anywhere">
|
||||||
|
{{ [row.province, row.city, row.county, row.addressDetail].filter(Boolean).join(' ') }}
|
||||||
|
<div v-if="!validPhone(row.tel)" style="color: #f56c6c">请先修改手机号码</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-radio-group>
|
||||||
|
<p v-else-if="!loading">{{ failed ? '地址加载失败' : '暂无收货地址' }}</p>
|
||||||
|
</div>
|
||||||
|
<div slot="footer">
|
||||||
|
<el-button v-if="failed" @click="loadAddresses">重新加载</el-button>
|
||||||
|
<el-button type="primary" :disabled="!selectedAddress || !validPhone(selectedAddress.tel) || loading || failed"
|
||||||
|
@click="confirmAddress">确定</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
<address-dialog ref="addressDialog" :address-api="addressApi"
|
||||||
|
@select_user_address="loadAddresses"></address-dialog>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
components: {
|
||||||
|
"address-dialog": ADDRESS_DIALOG
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
addressApi: "/platform/activity/worksCollection/addressManage",
|
||||||
|
visible: false,
|
||||||
|
addresses: [],
|
||||||
|
selectedId: "",
|
||||||
|
loading: false,
|
||||||
|
failed: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
selectedAddress() {
|
||||||
|
return this.addresses.find(row => row.id === this.selectedId)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
validPhone(value) {
|
||||||
|
return /^1[3-9][0-9]{9}$/.test(value)
|
||||||
|
},
|
||||||
|
open(address) {
|
||||||
|
this.visible = true
|
||||||
|
this.addresses = []
|
||||||
|
this.selectedId = address ? address.id : ""
|
||||||
|
this.loadAddresses()
|
||||||
|
},
|
||||||
|
async loadAddresses() {
|
||||||
|
this.loading = true
|
||||||
|
this.failed = false
|
||||||
|
try {
|
||||||
|
const response = await this.$axios.post(this.addressApi + "/selectUserAddress")
|
||||||
|
this.addresses = response.data
|
||||||
|
if (!this.selectedAddress) this.selectedId = ""
|
||||||
|
this.$emit("addresses-updated", this.addresses)
|
||||||
|
} catch (error) {
|
||||||
|
this.failed = true
|
||||||
|
} finally {
|
||||||
|
this.loading = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
addAddress() {
|
||||||
|
const dialog = this.$refs.addressDialog
|
||||||
|
dialog.formData = {}
|
||||||
|
dialog.dialogVisible = true
|
||||||
|
},
|
||||||
|
editAddress(row) {
|
||||||
|
this.$refs.addressDialog.openEdit({ ...row })
|
||||||
|
},
|
||||||
|
confirmAddress() {
|
||||||
|
if (!this.selectedAddress || !this.validPhone(this.selectedAddress.tel)) return
|
||||||
|
this.$emit("selected", this.selectedAddress)
|
||||||
|
this.visible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -41,12 +41,13 @@ let ADDRESS_DIALOG = {
|
|||||||
v-model="formData.userName"></el-input>
|
v-model="formData.userName"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item
|
<el-form-item
|
||||||
:rules="{required:true,message: '请填写手机号码', trigger: 'blur'}"
|
:rules="[{ required: true, message: '请填写手机号码', trigger: 'blur' },
|
||||||
|
{ pattern: /^1[3-9][0-9]{9}$/, message: '请输入正确的手机号码', trigger: 'blur' }]"
|
||||||
label="手机号码"
|
label="手机号码"
|
||||||
prop="tel">
|
prop="tel">
|
||||||
<el-input maxlength="11" placeholder="请填写手机号码"
|
<el-input maxlength="11" placeholder="请填写手机号码"
|
||||||
type="tel"
|
type="tel"
|
||||||
v-model="formData.tel"></el-input>
|
v-model.trim="formData.tel"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
|
||||||
@@ -57,6 +58,12 @@ let ADDRESS_DIALOG = {
|
|||||||
</el-dialog>
|
</el-dialog>
|
||||||
`,
|
`,
|
||||||
mixins: [initTableMixins],
|
mixins: [initTableMixins],
|
||||||
|
props: {
|
||||||
|
addressApi: {
|
||||||
|
type: String,
|
||||||
|
default: "/platform/welfare/addressManage"
|
||||||
|
}
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
dzOptions: chengShiList,
|
dzOptions: chengShiList,
|
||||||
@@ -90,7 +97,7 @@ let ADDRESS_DIALOG = {
|
|||||||
doSaveUserAddress() {
|
doSaveUserAddress() {
|
||||||
this.$refs["addForm"].validate(async (valid) => {
|
this.$refs["addForm"].validate(async (valid) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
const resp = await this.$axios.post("/platform/welfare/addressManage/doSaveUserAddress", { data: JSON.stringify(this.formData) })
|
const resp = await this.$axios.post(this.addressApi + "/doSaveUserAddress", { data: JSON.stringify(this.formData) })
|
||||||
if (resp.code === 0) {
|
if (resp.code === 0) {
|
||||||
this.$message({
|
this.$message({
|
||||||
message: resp.msg,
|
message: resp.msg,
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ layout("/layouts/platform.html"){
|
|||||||
</el-card>
|
</el-card>
|
||||||
</template>
|
</template>
|
||||||
</guava>
|
</guava>
|
||||||
<address-dialog ref="addressDialog" @select_user_address="selectUserAddress"></address-dialog>
|
<address-dialog ref="addressDialog" :address-api="addressApi" @select_user_address="selectUserAddress"></address-dialog>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -61,6 +61,7 @@ layout("/layouts/platform.html"){
|
|||||||
mixins: [initTableMixins],
|
mixins: [initTableMixins],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
addressApi: loc().replace(/\/$/, ""),
|
||||||
dzOptions: chengShiList,
|
dzOptions: chengShiList,
|
||||||
dialogVisible: false,
|
dialogVisible: false,
|
||||||
tableColumns: [
|
tableColumns: [
|
||||||
@@ -77,14 +78,14 @@ layout("/layouts/platform.html"){
|
|||||||
methods: {
|
methods: {
|
||||||
// 导出全部用户的收货地址,不传当前用户或分页条件;下载和 loading 复用全局方法。
|
// 导出全部用户的收货地址,不传当前用户或分页条件;下载和 loading 复用全局方法。
|
||||||
exportAllAddress() {
|
exportAllAddress() {
|
||||||
this.$downLoad("/platform/welfare/addressManage/exportAllAddress", {})
|
this.$downLoad(this.addressApi + "/exportAllAddress", {})
|
||||||
},
|
},
|
||||||
selectUserAddress(){
|
selectUserAddress(){
|
||||||
this.pageData()
|
this.pageData()
|
||||||
},
|
},
|
||||||
pageData() {
|
pageData() {
|
||||||
this.tableLoading = true
|
this.tableLoading = true
|
||||||
this.$axios.post("/platform/welfare/addressManage/selectUserAddress", this.pageForm).then((resp) => {
|
this.$axios.post(this.addressApi + "/selectUserAddress", this.pageForm).then((resp) => {
|
||||||
this.tableLoading = false
|
this.tableLoading = false
|
||||||
if (resp.code === 0) {
|
if (resp.code === 0) {
|
||||||
this.tableData = resp.data
|
this.tableData = resp.data
|
||||||
@@ -104,7 +105,7 @@ layout("/layouts/platform.html"){
|
|||||||
cancelButtonText: "取消",
|
cancelButtonText: "取消",
|
||||||
type: "warning"
|
type: "warning"
|
||||||
}).then(async () => {
|
}).then(async () => {
|
||||||
const resp = await this.$axios.post("/platform/welfare/addressManage/deleteAddress", { id: id })
|
const resp = await this.$axios.post(this.addressApi + "/deleteAddress", { id: id })
|
||||||
if (resp.code === 0) {
|
if (resp.code === 0) {
|
||||||
this.doSearch()
|
this.doSearch()
|
||||||
this.$message({
|
this.$message({
|
||||||
@@ -121,7 +122,7 @@ layout("/layouts/platform.html"){
|
|||||||
this.$refs.addressDialog.openEdit(row)
|
this.$refs.addressDialog.openEdit(row)
|
||||||
},
|
},
|
||||||
async doDefault(row) {
|
async doDefault(row) {
|
||||||
const resp = await this.$axios.post(loc() + "/doDefault", { id: row.id })
|
const resp = await this.$axios.post(this.addressApi + "/doDefault", { id: row.id })
|
||||||
if (resp.code === 0) {
|
if (resp.code === 0) {
|
||||||
this.doSearch()
|
this.doSearch()
|
||||||
this.$message({
|
this.$message({
|
||||||
|
|||||||
+230
@@ -2,6 +2,236 @@
|
|||||||
layout("/layouts/platform_h5.html"){
|
layout("/layouts/platform_h5.html"){
|
||||||
#-->
|
#-->
|
||||||
|
|
||||||
|
<style>
|
||||||
|
#app.works-activity-page {
|
||||||
|
min-height: 100%;
|
||||||
|
height: auto;
|
||||||
|
color: #323233;
|
||||||
|
}
|
||||||
|
|
||||||
|
.works-activity-page .van-nav-bar__title {
|
||||||
|
color: #323233;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.works-activity-page .van-nav-bar__arrow,
|
||||||
|
.works-activity-page .van-nav-bar__text {
|
||||||
|
color: var(--color-primary);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.works-activity-page .van-nav-bar__text {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.works-activity-page .van-nav-bar__text::after {
|
||||||
|
position: absolute;
|
||||||
|
right: 20%;
|
||||||
|
bottom: -6px;
|
||||||
|
left: 20%;
|
||||||
|
height: 2px;
|
||||||
|
border-radius: 2px;
|
||||||
|
background: currentColor;
|
||||||
|
content: "";
|
||||||
|
}
|
||||||
|
|
||||||
|
.works-activity-list {
|
||||||
|
box-sizing: border-box;
|
||||||
|
min-height: calc(100vh - 46px);
|
||||||
|
padding: 12px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.works-activity-card {
|
||||||
|
--cover-width: clamp(68px, 25vw, 108px);
|
||||||
|
--card-gap: clamp(8px, 3.5vw, 16px);
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: var(--cover-width) minmax(0, 1fr);
|
||||||
|
align-items: stretch;
|
||||||
|
gap: var(--card-gap);
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: 100%;
|
||||||
|
margin: 0 0 10px;
|
||||||
|
padding: 12px 10px;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 10px;
|
||||||
|
background: #fff;
|
||||||
|
color: inherit;
|
||||||
|
font: inherit;
|
||||||
|
text-align: left;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.works-activity-card:focus-visible {
|
||||||
|
outline: 2px solid var(--color-primary);
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.works-activity-cover {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: 9px;
|
||||||
|
background: #f7f8fa;
|
||||||
|
color: #c8c9cc;
|
||||||
|
font-size: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.works-activity-cover .van-image {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.works-activity-heading {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.works-activity-name {
|
||||||
|
display: block;
|
||||||
|
overflow: hidden;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1.3;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.works-activity-status {
|
||||||
|
display: inline-block;
|
||||||
|
box-sizing: border-box;
|
||||||
|
max-width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 1px 6px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-weight: 600;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
.works-activity-status--open {
|
||||||
|
background: var(--color-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.works-activity-status--upcoming {
|
||||||
|
background: #f2f3f5;
|
||||||
|
color: var(--color-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.works-activity-status--closed {
|
||||||
|
background: #969799;
|
||||||
|
}
|
||||||
|
|
||||||
|
.works-activity-dates {
|
||||||
|
display: grid;
|
||||||
|
gap: 2px;
|
||||||
|
margin-top: 7px;
|
||||||
|
color: #646566;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.works-activity-date {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.works-activity-date .van-icon {
|
||||||
|
flex-shrink: 0;
|
||||||
|
color: var(--color-primary);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div id="app" class="works-activity-page" v-cloak>
|
||||||
|
<van-nav-bar title="作品征集" left-arrow right-text="我的作品" fixed placeholder :border="false"
|
||||||
|
@click-left="historyBack" @click-right="$pjaxReplace(moduleUrl + '/upload/mine')"></van-nav-bar>
|
||||||
|
|
||||||
|
<van-pull-refresh v-model="refreshing" class="works-activity-list" @refresh="loadActivities">
|
||||||
|
<van-loading v-if="loading" style="padding: 24px; text-align: center"></van-loading>
|
||||||
|
<button v-for="activity in activities" :key="activity.id" type="button" class="works-activity-card"
|
||||||
|
@click="$pjaxReplace(moduleUrl + '/upload?activityId=' + encodeURIComponent(activity.id))">
|
||||||
|
<span class="works-activity-cover" aria-hidden="true">
|
||||||
|
<van-image v-if="activity.cover" :src="activity.cover" width="100%" height="100%" fit="cover" alt="">
|
||||||
|
<template #error><van-icon name="photo-o"></van-icon></template>
|
||||||
|
</van-image>
|
||||||
|
<van-icon v-else name="photo-o"></van-icon>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
<span class="works-activity-heading">
|
||||||
|
<strong class="works-activity-name" :title="activity.name">{{ activity.name }}</strong>
|
||||||
|
<van-tag class="works-activity-status" :class="'works-activity-status--' + activity.status">
|
||||||
|
{{ statuses[activity.status] }}
|
||||||
|
</van-tag>
|
||||||
|
</span>
|
||||||
|
<span class="works-activity-dates">
|
||||||
|
<span class="works-activity-date">
|
||||||
|
<van-icon name="calendar-o" aria-hidden="true"></van-icon>
|
||||||
|
<span>开始:{{ formatDate(activity.startDateTime) }}</span>
|
||||||
|
</span>
|
||||||
|
<span class="works-activity-date">
|
||||||
|
<van-icon name="calendar-o" aria-hidden="true"></van-icon>
|
||||||
|
<span>截止:{{ formatDate(activity.endDateTime) }}</span>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
<van-empty v-if="!loading && !failed && !activities.length" description="暂无作品征集活动"></van-empty>
|
||||||
|
<van-empty v-if="!loading && failed" description="活动加载失败">
|
||||||
|
<van-button size="small" @click="loadActivities">重新加载</van-button>
|
||||||
|
</van-empty>
|
||||||
|
</van-pull-refresh>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
new Vue({
|
||||||
|
el: "#app",
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
moduleUrl: "/platform/h5/activity/worksCollection",
|
||||||
|
activities: [],
|
||||||
|
statuses: {
|
||||||
|
open: "征集中",
|
||||||
|
upcoming: "未开始",
|
||||||
|
closed: "已结束"
|
||||||
|
},
|
||||||
|
loading: false,
|
||||||
|
refreshing: false,
|
||||||
|
failed: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
formatDate(value) {
|
||||||
|
return value ? this.$moment(value).format("YYYY-MM-DD HH:mm") : "—"
|
||||||
|
},
|
||||||
|
async loadActivities() {
|
||||||
|
if (this.loading) {
|
||||||
|
this.refreshing = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.loading = true
|
||||||
|
this.failed = false
|
||||||
|
try {
|
||||||
|
const response = await this.$axios.post(this.moduleUrl + "/activities")
|
||||||
|
this.activities = response.data
|
||||||
|
} catch (error) {
|
||||||
|
this.failed = true
|
||||||
|
} finally {
|
||||||
|
this.loading = false
|
||||||
|
this.refreshing = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.loadActivities()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
<!--#
|
<!--#
|
||||||
}
|
}
|
||||||
#-->
|
#-->
|
||||||
|
|||||||
@@ -0,0 +1,86 @@
|
|||||||
|
<!--#
|
||||||
|
layout("/layouts/platform_h5.html"){
|
||||||
|
#-->
|
||||||
|
|
||||||
|
<div id="app" v-cloak>
|
||||||
|
<van-nav-bar title="选择收货地址" left-arrow fixed placeholder @click-left="finish"></van-nav-bar>
|
||||||
|
<van-notice-bar wrapable :scrollable="false"
|
||||||
|
text="请选择活动纪念品的收货地址。"></van-notice-bar>
|
||||||
|
|
||||||
|
<van-loading v-if="loading" style="padding: 24px; text-align: center"></van-loading>
|
||||||
|
<van-empty v-else-if="failed" description="地址加载失败">
|
||||||
|
<van-button size="small" @click="loadAddresses">重新加载</van-button>
|
||||||
|
</van-empty>
|
||||||
|
<template v-else>
|
||||||
|
<van-address-list v-if="addresses.length" :list="addresses" default-tag-text="默认"
|
||||||
|
add-button-text="新增地址" @select="confirmAddress" @edit="openEditor"
|
||||||
|
@add="openEditor()"></van-address-list>
|
||||||
|
<van-empty v-else description="暂无收货地址">
|
||||||
|
<van-button round type="primary" @click="openEditor()">新增地址</van-button>
|
||||||
|
</van-empty>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
new Vue({
|
||||||
|
el: "#app",
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
addressApi: "/platform/activity/worksCollection/addressManage",
|
||||||
|
addresses: [],
|
||||||
|
loading: false,
|
||||||
|
failed: false,
|
||||||
|
saving: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async loadAddresses() {
|
||||||
|
this.loading = true
|
||||||
|
this.failed = false
|
||||||
|
try {
|
||||||
|
const response = await this.$axios.post(this.addressApi + "/selectUserAddress")
|
||||||
|
this.addresses = response.data.map(row => ({
|
||||||
|
...row,
|
||||||
|
name: row.userName,
|
||||||
|
address: [row.province, row.city, row.county, row.addressDetail].filter(Boolean).join(" ")
|
||||||
|
}))
|
||||||
|
} catch (error) {
|
||||||
|
this.failed = true
|
||||||
|
} finally {
|
||||||
|
this.loading = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
openEditor(row) {
|
||||||
|
if (this.saving) return
|
||||||
|
const query = new URLSearchParams({ fromPicker: "1" })
|
||||||
|
if (row) query.set("id", row.id)
|
||||||
|
this.$pjaxReplace("/platform/h5/activity/worksCollection/upload/address/edit?" + query.toString())
|
||||||
|
},
|
||||||
|
async confirmAddress(row) {
|
||||||
|
if (this.saving) return
|
||||||
|
if (!/^1[3-9][0-9]{9}$/.test(row.tel)) {
|
||||||
|
this.$toast("请先修改手机号码")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.saving = true
|
||||||
|
try {
|
||||||
|
await this.$axios.post(this.addressApi + "/doDefault", { id: row.id })
|
||||||
|
this.$toast.success("已确认收货地址")
|
||||||
|
this.finish()
|
||||||
|
} finally {
|
||||||
|
this.saving = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
finish() {
|
||||||
|
this.$pjaxReplace("/platform/h5/activity/worksCollection/upload/mine")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.loadAddresses()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!--#
|
||||||
|
}
|
||||||
|
#-->
|
||||||
+130
@@ -0,0 +1,130 @@
|
|||||||
|
<!--#
|
||||||
|
layout("/layouts/platform_h5.html"){
|
||||||
|
#-->
|
||||||
|
<style>
|
||||||
|
.work-address-editor .van-address-edit__buttons {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row-reverse;
|
||||||
|
gap: 12px;
|
||||||
|
padding: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.work-address-editor .van-address-edit__buttons .van-button {
|
||||||
|
flex: 1;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.work-address-editor .van-address-edit__buttons .van-button--danger {
|
||||||
|
background: var(--color-primary, #1989fa);
|
||||||
|
border-color: var(--color-primary, #1989fa);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<div id="app" v-cloak>
|
||||||
|
<van-nav-bar :title="addressId ? '修改收货地址' : '新增收货地址'" left-arrow fixed placeholder
|
||||||
|
@click-left="finish"></van-nav-bar>
|
||||||
|
<van-loading v-if="loading" style="padding: 24px; text-align: center"></van-loading>
|
||||||
|
<van-empty v-else-if="failed" description="无法加载收货地址">
|
||||||
|
<van-button size="small" @click="loadAddress">重新加载</van-button>
|
||||||
|
</van-empty>
|
||||||
|
<van-address-edit v-else class="work-address-editor" :address-info="addressInfo" :area-list="areaList"
|
||||||
|
:area-columns-placeholder="['请选择', '请选择', '请选择']"
|
||||||
|
:detail-maxlength="100" :detail-rows="2" :tel-maxlength="11" :tel-validator="validPhone"
|
||||||
|
:show-delete="!!addressId" show-set-default :is-saving="saving" :is-deleting="deleting"
|
||||||
|
delete-button-text="删除地址" save-button-text="保存"
|
||||||
|
@save="saveAddress" @delete="deleteAddress"></van-address-edit>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
<!--#include("/platform/zhghh5/welfare/include/areaList.js"){}#-->
|
||||||
|
new Vue({
|
||||||
|
el: "#app",
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
addressApi: "/platform/activity/worksCollection/addressManage",
|
||||||
|
uploadUrl: "/platform/h5/activity/worksCollection/upload",
|
||||||
|
addressId: GetQueryString("id"),
|
||||||
|
activityId: GetQueryString("activityId"),
|
||||||
|
workId: GetQueryString("workId"),
|
||||||
|
fromPicker: GetQueryString("fromPicker") === "1",
|
||||||
|
areaList,
|
||||||
|
addressInfo: {},
|
||||||
|
loading: false,
|
||||||
|
failed: false,
|
||||||
|
saving: false,
|
||||||
|
deleting: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
validPhone(value) {
|
||||||
|
return /^1[3-9][0-9]{9}$/.test(value)
|
||||||
|
},
|
||||||
|
async loadAddress() {
|
||||||
|
if (!this.addressId) return
|
||||||
|
this.loading = true
|
||||||
|
this.failed = false
|
||||||
|
try {
|
||||||
|
const { data } = await this.$axios.post(this.addressApi + "/selectUserAddress")
|
||||||
|
const row = data.find(address => address.id === this.addressId)
|
||||||
|
if (row) {
|
||||||
|
this.addressInfo = { ...row, name: row.userName }
|
||||||
|
} else {
|
||||||
|
this.failed = true
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
this.failed = true
|
||||||
|
} finally {
|
||||||
|
this.loading = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async saveAddress(row) {
|
||||||
|
if (this.saving || this.deleting) return
|
||||||
|
this.saving = true
|
||||||
|
try {
|
||||||
|
await this.$axios.post(this.addressApi + "/doSaveUserAddress", {
|
||||||
|
data: JSON.stringify({ ...row, id: this.addressId, userName: row.name })
|
||||||
|
})
|
||||||
|
this.$toast.success("地址已保存")
|
||||||
|
this.finish()
|
||||||
|
} catch (error) {
|
||||||
|
// 公共请求处理会显示错误信息。
|
||||||
|
} finally {
|
||||||
|
this.saving = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async deleteAddress() {
|
||||||
|
if (!this.addressId || this.saving || this.deleting) return
|
||||||
|
this.deleting = true
|
||||||
|
try {
|
||||||
|
await this.$dialog.confirm({ message: "确定删除这个收货地址吗?" })
|
||||||
|
await this.$axios.post(this.addressApi + "/deleteAddress", { id: this.addressId })
|
||||||
|
this.$toast.success("地址已删除")
|
||||||
|
this.finish()
|
||||||
|
} catch (error) {
|
||||||
|
// 取消确认或请求失败时留在当前页。
|
||||||
|
} finally {
|
||||||
|
this.deleting = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
finish() {
|
||||||
|
if (this.fromPicker && window.history.length > 1) {
|
||||||
|
this.historyBack()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!this.activityId) {
|
||||||
|
this.$pjaxReplace(this.uploadUrl + "/address")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const query = new URLSearchParams({ activityId: this.activityId })
|
||||||
|
if (this.workId) query.set("id", this.workId)
|
||||||
|
this.$pjaxReplace(this.uploadUrl + "?" + query.toString())
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.loadAddress()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!--#
|
||||||
|
}
|
||||||
|
#-->
|
||||||
+489
-1
@@ -1,7 +1,495 @@
|
|||||||
<!--#
|
<!--#
|
||||||
layout("/layouts/platform_h5.html"){
|
layout("/layouts/platform_h5.html"){
|
||||||
#-->
|
#-->
|
||||||
22222222222
|
<style>
|
||||||
|
.work-activity-detail .van-cell__title {
|
||||||
|
min-width: 0;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.work-activity-detail .activity-detail-content {
|
||||||
|
margin-top: 8px;
|
||||||
|
color: #323233;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.work-activity-detail .activity-detail-content > .content {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.work-activity-detail .activity-detail-content > .content > :first-child {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.work-activity-detail .activity-detail-content > .content > :last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.work-upload-form .shipping-address-contact {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 2px 8px;
|
||||||
|
color: #323233;
|
||||||
|
}
|
||||||
|
|
||||||
|
.work-upload-form .shipping-address-value {
|
||||||
|
min-width: 0;
|
||||||
|
overflow-wrap: anywhere;
|
||||||
|
}
|
||||||
|
|
||||||
|
.work-upload-form .shipping-address-placeholder {
|
||||||
|
color: #969799;
|
||||||
|
}
|
||||||
|
|
||||||
|
.work-upload-form .shipping-address-detail {
|
||||||
|
margin-top: 2px;
|
||||||
|
color: #646566;
|
||||||
|
}
|
||||||
|
|
||||||
|
.work-upload-form .van-field__label {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.work-upload-form .van-field:not(.direction-column-field) .van-field__label {
|
||||||
|
width: 64px;
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.work-upload-form .attachment-field {
|
||||||
|
row-gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.work-upload-form .attachment-field .van-field__control {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.work-upload-form .attachment-hint {
|
||||||
|
display: block;
|
||||||
|
margin-top: 2px;
|
||||||
|
color: #969799;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
.work-address-picker .van-address-list {
|
||||||
|
padding-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.work-address-picker .van-address-list__bottom {
|
||||||
|
position: static;
|
||||||
|
padding: 12px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.work-address-picker .van-address-list__add {
|
||||||
|
margin: 0;
|
||||||
|
background: var(--color-primary, #1989fa);
|
||||||
|
border-color: var(--color-primary, #1989fa);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<div id="app" v-cloak>
|
||||||
|
<van-nav-bar :title="workId ? '编辑作品' : '征集详情'" left-arrow fixed placeholder
|
||||||
|
@click-left="historyBack"></van-nav-bar>
|
||||||
|
|
||||||
|
<van-loading v-if="loading" style="padding: 24px; text-align: center"></van-loading>
|
||||||
|
<van-empty v-else-if="failed" description="无法加载活动或作品">
|
||||||
|
<van-button size="small" @click="loadForm">重新加载</van-button>
|
||||||
|
</van-empty>
|
||||||
|
|
||||||
|
<template v-else-if="activity">
|
||||||
|
<van-image v-if="activity.cover" :src="activity.cover" width="100%" height="200px" fit="cover"></van-image>
|
||||||
|
<van-cell :title="activity.name">
|
||||||
|
<template #label>
|
||||||
|
<div>开始:{{ formatDate(activity.startDateTime) }}</div>
|
||||||
|
<div>截止:{{ formatDate(activity.endDateTime) }}</div>
|
||||||
|
</template>
|
||||||
|
</van-cell>
|
||||||
|
<van-cell v-if="activity.introduce" title="活动介绍" class="work-activity-detail">
|
||||||
|
<template #label>
|
||||||
|
<rich-text class="activity-detail-content" :value="activity.introduce"></rich-text>
|
||||||
|
</template>
|
||||||
|
</van-cell>
|
||||||
|
<van-cell v-if="activity.content" title="活动内容" class="work-activity-detail">
|
||||||
|
<template #label>
|
||||||
|
<rich-text class="activity-detail-content" :value="activity.content"></rich-text>
|
||||||
|
</template>
|
||||||
|
</van-cell>
|
||||||
|
<van-cell v-if="activity.rewardMethod" title="奖励方式" class="work-activity-detail">
|
||||||
|
<template #label>
|
||||||
|
<rich-text class="activity-detail-content" :value="activity.rewardMethod"></rich-text>
|
||||||
|
</template>
|
||||||
|
</van-cell>
|
||||||
|
|
||||||
|
<van-notice-bar v-if="activity.status !== 'open'" :text="activity.status === 'upcoming' ? '征集尚未开始' : '征集已结束'"></van-notice-bar>
|
||||||
|
<van-notice-bar v-else-if="!activity.subjectTypes.length" text="该活动暂无可投稿的主题"></van-notice-bar>
|
||||||
|
<van-form v-else class="form-container work-upload-form" @submit="submitWork" @failed="handleSubmitFailure" :disabled="uploading || submitting">
|
||||||
|
<van-cell-group title="作品信息">
|
||||||
|
<van-field label="主题类型" :value="selectedSubject ? selectedSubject.typeName : ''" placeholder="请选择主题类型"
|
||||||
|
readonly required :is-link="!uploading && !submitting" :clickable="!uploading && !submitting"
|
||||||
|
@click="!uploading && !submitting && (showSubjectPicker = true)"></van-field>
|
||||||
|
<van-field label="作品类型" :value="selectedType ? selectedType.worksTypeName : ''" :placeholder="worksTypePlaceholder"
|
||||||
|
readonly required :disabled="!worksTypes.length || uploading || submitting"
|
||||||
|
:is-link="!!worksTypes.length && !uploading && !submitting"
|
||||||
|
:clickable="!!worksTypes.length && !uploading && !submitting"
|
||||||
|
@click="worksTypes.length && !uploading && !submitting && (showWorksPicker = true)"></van-field>
|
||||||
|
<van-field v-model.trim="form.name" name="name" label="作品名称" placeholder="请输入作品名称" required maxlength="100"
|
||||||
|
:rules="[{ required: true, message: '请输入作品名称' }]"></van-field>
|
||||||
|
<van-field v-model.trim="form.description" name="description" label="作品描述" placeholder="请输入作品描述" required
|
||||||
|
type="textarea" autosize rows="3" :maxlength="descriptionLimit" show-word-limit
|
||||||
|
:rules="[{ required: true, message: '请输入作品描述' }]"></van-field>
|
||||||
|
<van-field label="收货地址" readonly required is-link clickable @click="openAddressPicker">
|
||||||
|
<template #input>
|
||||||
|
<div v-if="shippingAddress" class="shipping-address-value">
|
||||||
|
<div class="shipping-address-contact">
|
||||||
|
<span>{{ shippingAddress.userName }}</span>
|
||||||
|
<span>{{ shippingAddress.tel }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="shipping-address-detail">{{ shippingAddress.address }}</div>
|
||||||
|
</div>
|
||||||
|
<span v-else class="shipping-address-placeholder">请选择活动纪念品收货地址</span>
|
||||||
|
</template>
|
||||||
|
</van-field>
|
||||||
|
<van-field label="作品附件" required class="direction-column-field attachment-field">
|
||||||
|
<template #label>
|
||||||
|
<span>作品附件</span>
|
||||||
|
<span v-if="attachmentHint" class="attachment-hint">{{ attachmentHint }}</span>
|
||||||
|
</template>
|
||||||
|
<template #input>
|
||||||
|
<van-uploader v-model="attachments" :accept="fileAccept" :max-count="fileCountLimit"
|
||||||
|
:disabled="!selectedType || uploading || submitting" :deletable="!uploading && !submitting"
|
||||||
|
:before-read="validateFiles" :after-read="uploadFiles" result-type="file"
|
||||||
|
multiple></van-uploader>
|
||||||
|
</template>
|
||||||
|
</van-field>
|
||||||
|
</van-cell-group>
|
||||||
|
<div class="form-actions">
|
||||||
|
<van-button block type="primary" native-type="submit" :loading="submitting" :disabled="uploading">
|
||||||
|
{{ workId ? '保存修改' : '提交作品' }}
|
||||||
|
</van-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<van-popup v-model="showSubjectPicker" position="bottom" round safe-area-inset-bottom>
|
||||||
|
<van-picker v-if="showSubjectPicker" show-toolbar title="主题类型" :columns="activity.subjectTypes" value-key="typeName"
|
||||||
|
:default-index="subjectPickerIndex" @cancel="showSubjectPicker = false" @confirm="changeSubject"></van-picker>
|
||||||
|
</van-popup>
|
||||||
|
<van-popup v-model="showWorksPicker" position="bottom" round safe-area-inset-bottom>
|
||||||
|
<van-picker v-if="showWorksPicker" show-toolbar title="作品类型" :columns="worksTypes" value-key="worksTypeName"
|
||||||
|
:default-index="worksPickerIndex" @cancel="showWorksPicker = false" @confirm="changeWorksType"></van-picker>
|
||||||
|
</van-popup>
|
||||||
|
</van-form>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<van-action-sheet v-model="showAddressPicker" class="work-address-picker" title="选择收货地址" :close-on-click-overlay="false">
|
||||||
|
<van-loading v-if="addressLoading" style="padding: 20px; text-align: center"></van-loading>
|
||||||
|
<van-empty v-else-if="addressFailed" description="地址加载失败">
|
||||||
|
<van-button size="small" @click="loadAddresses()">重新加载</van-button>
|
||||||
|
</van-empty>
|
||||||
|
<van-address-list v-else-if="addresses.length" :value="shippingAddress ? shippingAddress.id : ''"
|
||||||
|
:list="addresses" default-tag-text="默认" add-button-text="新增地址"
|
||||||
|
@select="useAddress" @edit="editAddress" @add="editAddress()"></van-address-list>
|
||||||
|
<van-empty v-else description="暂无收货地址">
|
||||||
|
<van-button round type="primary" @click="editAddress()">新增地址</van-button>
|
||||||
|
</van-empty>
|
||||||
|
</van-action-sheet>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
new Vue({
|
||||||
|
el: "#app",
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
moduleUrl: "/platform/h5/activity/worksCollection",
|
||||||
|
activityId: GetQueryString("activityId"),
|
||||||
|
workId: GetQueryString("id"),
|
||||||
|
activity: null,
|
||||||
|
form: { subjectId: "", worksId: "", name: "", description: "" },
|
||||||
|
attachments: [],
|
||||||
|
addressApi: "/platform/activity/worksCollection/addressManage",
|
||||||
|
addresses: [],
|
||||||
|
shippingAddress: null,
|
||||||
|
addressLoading: false,
|
||||||
|
addressFailed: false,
|
||||||
|
showAddressPicker: false,
|
||||||
|
showSubjectPicker: false,
|
||||||
|
showWorksPicker: false,
|
||||||
|
loading: false,
|
||||||
|
failed: false,
|
||||||
|
uploading: false,
|
||||||
|
submitting: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
selectedSubject() {
|
||||||
|
return this.activity.subjectTypes.find(item => item.id === this.form.subjectId)
|
||||||
|
},
|
||||||
|
worksTypes() {
|
||||||
|
return this.selectedSubject ? this.selectedSubject.worksTypes : []
|
||||||
|
},
|
||||||
|
selectedType() {
|
||||||
|
return this.worksTypes.find(item => item.id === this.form.worksId)
|
||||||
|
},
|
||||||
|
worksTypePlaceholder() {
|
||||||
|
if (!this.selectedSubject) return "请先选择主题类型"
|
||||||
|
return this.worksTypes.length ? "请选择作品类型" : "该主题暂无作品类型"
|
||||||
|
},
|
||||||
|
subjectPickerIndex() {
|
||||||
|
return Math.max(0, this.activity.subjectTypes.findIndex(item => item.id === this.form.subjectId))
|
||||||
|
},
|
||||||
|
worksPickerIndex() {
|
||||||
|
return Math.max(0, this.worksTypes.findIndex(item => item.id === this.form.worksId))
|
||||||
|
},
|
||||||
|
descriptionLimit() {
|
||||||
|
const limit = this.selectedType && this.selectedType.maxWordCount
|
||||||
|
return limit > 0 ? Math.min(100, limit) : 100
|
||||||
|
},
|
||||||
|
fileCountLimit() {
|
||||||
|
const limit = this.selectedType && this.selectedType.allowFileNum
|
||||||
|
return limit > 0 ? limit : Infinity
|
||||||
|
},
|
||||||
|
allowedExtensions() {
|
||||||
|
return (this.selectedType && this.selectedType.allowFileTypes || []).map(type => type.toLowerCase())
|
||||||
|
},
|
||||||
|
fileAccept() {
|
||||||
|
return this.allowedExtensions.length ? this.allowedExtensions.map(type => "." + type).join(",") : "*/*"
|
||||||
|
},
|
||||||
|
attachmentHint() {
|
||||||
|
if (!this.selectedType) return "请先选择作品类型"
|
||||||
|
const hints = []
|
||||||
|
if (this.allowedExtensions.length) hints.push(this.allowedExtensions.join("、"))
|
||||||
|
if (Number.isFinite(this.fileCountLimit)) hints.push("最多 " + this.fileCountLimit + " 个附件")
|
||||||
|
if (this.selectedType.allowSingleFileSize > 0) hints.push("单个不超过 " + this.selectedType.allowSingleFileSize + " KB")
|
||||||
|
if (this.selectedType.allowTotalFileSize > 0) hints.push("总计不超过 " + this.selectedType.allowTotalFileSize + " KB")
|
||||||
|
return hints.join(",")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
validPhone(value) {
|
||||||
|
return /^1[3-9][0-9]{9}$/.test(value)
|
||||||
|
},
|
||||||
|
addressText(row) {
|
||||||
|
return [row.province, row.city, row.county, row.addressDetail].filter(Boolean).join("")
|
||||||
|
},
|
||||||
|
async loadAddresses(useDefault = false) {
|
||||||
|
if (this.addressLoading) return
|
||||||
|
this.addressLoading = true
|
||||||
|
this.addressFailed = false
|
||||||
|
try {
|
||||||
|
const { data } = await this.$axios.post(this.addressApi + "/selectUserAddress")
|
||||||
|
this.addresses = data.map(row => ({ ...row, name: row.userName, address: this.addressText(row) }))
|
||||||
|
if (this.shippingAddress) {
|
||||||
|
this.shippingAddress = this.addresses.find(row => row.id === this.shippingAddress.id && this.validPhone(row.tel)) || null
|
||||||
|
} else if (useDefault && !this.showAddressPicker) {
|
||||||
|
this.shippingAddress = this.addresses.find(row => row.isDefault && this.validPhone(row.tel)) || null
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
this.addressFailed = true
|
||||||
|
} finally {
|
||||||
|
this.addressLoading = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
openAddressPicker() {
|
||||||
|
if (this.submitting || this.uploading) return
|
||||||
|
this.showAddressPicker = true
|
||||||
|
this.loadAddresses()
|
||||||
|
},
|
||||||
|
draftKey() {
|
||||||
|
return ["works-address-return", store.state.user.id, this.activityId, this.workId || "new"].join(":")
|
||||||
|
},
|
||||||
|
editAddress(row) {
|
||||||
|
if (this.uploading || this.submitting) return
|
||||||
|
const draft = {
|
||||||
|
form: this.form,
|
||||||
|
attachments: this.attachments.filter(file => file.url && file.status !== "failed")
|
||||||
|
.map(({ url, name, size, isImage, status }) => ({ url, name, size, isImage, status })),
|
||||||
|
shippingAddress: this.shippingAddress
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
sessionStorage.setItem(this.draftKey(), JSON.stringify(draft))
|
||||||
|
} catch (error) {
|
||||||
|
this.$toast.fail("暂时无法保留投稿内容,请重试")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const query = new URLSearchParams({ activityId: this.activityId, fromPicker: "1" })
|
||||||
|
if (this.workId) query.set("workId", this.workId)
|
||||||
|
if (row) query.set("id", row.id)
|
||||||
|
this.showAddressPicker = false
|
||||||
|
this.$pjaxReplace(this.moduleUrl + "/upload/address/edit?" + query.toString())
|
||||||
|
},
|
||||||
|
useAddress(row) {
|
||||||
|
if (!this.validPhone(row.tel)) {
|
||||||
|
this.$toast("请先修改手机号码")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.shippingAddress = row
|
||||||
|
this.showAddressPicker = false
|
||||||
|
},
|
||||||
|
restoreAddressDraft() {
|
||||||
|
try {
|
||||||
|
const stored = sessionStorage.getItem(this.draftKey())
|
||||||
|
if (!stored) return
|
||||||
|
sessionStorage.removeItem(this.draftKey())
|
||||||
|
const draft = JSON.parse(stored)
|
||||||
|
this.form = draft.form
|
||||||
|
this.attachments = draft.attachments
|
||||||
|
this.shippingAddress = draft.shippingAddress
|
||||||
|
this.openAddressPicker()
|
||||||
|
} catch (error) {
|
||||||
|
this.$toast.fail("无法恢复投稿草稿")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
formatDate(value) {
|
||||||
|
return value ? this.$moment(value).format("YYYY-MM-DD HH:mm") : "—"
|
||||||
|
},
|
||||||
|
async loadForm() {
|
||||||
|
this.loading = true
|
||||||
|
this.failed = false
|
||||||
|
try {
|
||||||
|
const { data } = await this.$axios.post(this.moduleUrl + "/activityDetail", { activityId: this.activityId })
|
||||||
|
if (this.workId) {
|
||||||
|
const { data: work } = await this.$axios.post(this.moduleUrl + "/myWork", { id: this.workId })
|
||||||
|
if (work.activityId !== data.id) throw new Error("作品与活动不匹配")
|
||||||
|
this.form = {
|
||||||
|
subjectId: work.subjectId,
|
||||||
|
worksId: work.worksId,
|
||||||
|
name: work.name,
|
||||||
|
description: work.description
|
||||||
|
}
|
||||||
|
this.attachments = (work.files || []).map(file => ({
|
||||||
|
name: file.name,
|
||||||
|
url: file.response.data,
|
||||||
|
size: file.size,
|
||||||
|
isImage: this.isImage(file.name)
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
this.activity = data
|
||||||
|
this.restoreAddressDraft()
|
||||||
|
} catch (error) {
|
||||||
|
this.failed = true
|
||||||
|
} finally {
|
||||||
|
this.loading = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
changeSubject(subject) {
|
||||||
|
this.showSubjectPicker = false
|
||||||
|
if (subject.id !== this.form.subjectId) {
|
||||||
|
this.form.subjectId = subject.id
|
||||||
|
this.form.worksId = ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
changeWorksType(type) {
|
||||||
|
this.showWorksPicker = false
|
||||||
|
this.form.worksId = type.id
|
||||||
|
},
|
||||||
|
isImage(name) {
|
||||||
|
return /\.(jpe?g|png|gif|bmp|webp)$/i.test(name)
|
||||||
|
},
|
||||||
|
validateFiles(input) {
|
||||||
|
if (!this.selectedType || this.uploading || this.submitting) return false
|
||||||
|
const files = Array.isArray(input) ? input : [input]
|
||||||
|
if (this.attachments.length + files.length > this.fileCountLimit) {
|
||||||
|
this.$toast("附件数量超过限制")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
const singleLimit = this.selectedType.allowSingleFileSize
|
||||||
|
for (const file of files) {
|
||||||
|
const extension = file.name.includes(".") ? file.name.split(".").pop().toLowerCase() : ""
|
||||||
|
if (this.allowedExtensions.length && !this.allowedExtensions.includes(extension)) {
|
||||||
|
this.$toast("附件格式不符合要求")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (singleLimit > 0 && file.size > singleLimit * 1024) {
|
||||||
|
this.$toast("单个附件大小超过限制")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const totalLimit = this.selectedType.allowTotalFileSize
|
||||||
|
const totalBytes = files.reduce((sum, file) => sum + file.size, 0)
|
||||||
|
+ this.attachments.reduce((sum, file) => sum + (file.size || 0), 0)
|
||||||
|
if (totalLimit > 0 && totalBytes > totalLimit * 1024) {
|
||||||
|
this.$toast("附件总大小超过限制")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
async uploadFiles(input) {
|
||||||
|
const items = Array.isArray(input) ? input : [input]
|
||||||
|
this.uploading = true
|
||||||
|
try {
|
||||||
|
await Promise.all(items.map(async item => {
|
||||||
|
this.$set(item, "status", "uploading")
|
||||||
|
try {
|
||||||
|
const body = new FormData()
|
||||||
|
body.append("file", item.file)
|
||||||
|
const { data } = await this.$axios.post("/platform/sys/file/uploadDynamicReturnUrl", body, {
|
||||||
|
headers: { "Content-Type": "multipart/form-data" }
|
||||||
|
})
|
||||||
|
this.$set(item, "url", data)
|
||||||
|
this.$set(item, "name", item.file.name)
|
||||||
|
this.$set(item, "size", item.file.size)
|
||||||
|
this.$set(item, "isImage", this.isImage(item.file.name))
|
||||||
|
this.$set(item, "status", "done")
|
||||||
|
} catch (error) {
|
||||||
|
this.$set(item, "status", "failed")
|
||||||
|
this.$set(item, "message", "上传失败")
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
} finally {
|
||||||
|
this.uploading = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleSubmitFailure() {
|
||||||
|
if (!this.shippingAddress && !this.uploading) this.openAddressPicker()
|
||||||
|
},
|
||||||
|
async submitWork() {
|
||||||
|
if (this.uploading || this.submitting) return
|
||||||
|
if (!this.shippingAddress || !this.validPhone(this.shippingAddress.tel)) {
|
||||||
|
this.openAddressPicker()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!this.selectedType) {
|
||||||
|
this.$toast("请选择主题类型和作品类型")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (this.form.description.length > this.descriptionLimit) {
|
||||||
|
this.$toast("作品描述超过字数限制")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!this.attachments.length || this.attachments.some(file => !file.url || file.status === "failed")) {
|
||||||
|
this.$toast("请上传附件并移除上传失败的文件")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.submitting = true
|
||||||
|
try {
|
||||||
|
await this.$dialog.confirm({ message: this.workId ? "确定保存修改吗?" : "确定提交这件作品吗?" })
|
||||||
|
await this.$axios.post(this.moduleUrl + "/saveWork", {
|
||||||
|
addressId: this.shippingAddress.id,
|
||||||
|
data: JSON.stringify({
|
||||||
|
...this.form,
|
||||||
|
id: this.workId,
|
||||||
|
activityId: this.activityId,
|
||||||
|
files: this.attachments.map(file => ({ response: { data: file.url } }))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
this.$toast.success(this.workId ? "保存成功" : "提交成功")
|
||||||
|
if (this.workId) {
|
||||||
|
this.historyBack()
|
||||||
|
} else {
|
||||||
|
this.$pjaxReplace(this.moduleUrl + "/upload/mine")
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// 请求失败由公共响应处理显示。
|
||||||
|
} finally {
|
||||||
|
this.submitting = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.loadForm()
|
||||||
|
this.loadAddresses(true)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
<!--#
|
<!--#
|
||||||
}
|
}
|
||||||
#-->
|
#-->
|
||||||
|
|||||||
+301
-8
@@ -1,8 +1,301 @@
|
|||||||
<!doctype html>
|
<!--#
|
||||||
<html lang="en">
|
layout("/layouts/platform_h5.html"){
|
||||||
<head>
|
#-->
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<title>Title</title>
|
<style>
|
||||||
</head>
|
.my-works-list {
|
||||||
<body></body>
|
padding: 14px 10px;
|
||||||
</html>
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-works-list .work-card {
|
||||||
|
margin-bottom: 14px;
|
||||||
|
padding: 14px 12px 0;
|
||||||
|
border-radius: 14px;
|
||||||
|
background: #fff;
|
||||||
|
color: #323233;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-works-list .work-summary {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-works-list .work-cover {
|
||||||
|
width: 82px;
|
||||||
|
height: 58px;
|
||||||
|
flex: 0 0 82px;
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: #f7f8fa;
|
||||||
|
color: #c8c9cc;
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-works-list .work-heading,
|
||||||
|
.my-works-list .work-metadata-value {
|
||||||
|
min-width: 0;
|
||||||
|
overflow-wrap: anywhere;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-works-list .work-title,
|
||||||
|
.my-works-list .work-name {
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-works-list .work-title {
|
||||||
|
margin: 0 0 5px;
|
||||||
|
font-size: 17px;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-works-list .work-name {
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-works-list .work-metadata {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1.2fr);
|
||||||
|
margin: 16px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-works-list .work-metadata-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 5px;
|
||||||
|
padding: 0 6px;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-works-list .work-metadata-item + .work-metadata-item {
|
||||||
|
border-left: 1px solid #ebedf0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-works-list .work-metadata-item .van-icon {
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-top: 1px;
|
||||||
|
color: var(--color-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-works-list .work-metadata-value {
|
||||||
|
margin-top: 3px;
|
||||||
|
color: #323233;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-works-list .work-more {
|
||||||
|
width: 100%;
|
||||||
|
min-height: 44px;
|
||||||
|
border: 0;
|
||||||
|
border-top: 1px solid #ebedf0;
|
||||||
|
background: transparent;
|
||||||
|
color: var(--color-primary);
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 600;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-works-list .work-detail {
|
||||||
|
padding: 8px 0 12px;
|
||||||
|
border-top: 1px solid #ebedf0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-works-list .work-detail-enter-active {
|
||||||
|
transition: opacity 160ms ease, transform 160ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-works-list .work-detail-enter {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-4px);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
.my-works-list .work-detail-enter-active {
|
||||||
|
transition: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-works-list .work-field {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 64px minmax(0, 1fr);
|
||||||
|
gap: 8px;
|
||||||
|
padding: 5px 0;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-works-list .work-field-label {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-works-list .work-field-value {
|
||||||
|
min-width: 0;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
overflow-wrap: anywhere;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-works-list .work-actions {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: 8px;
|
||||||
|
padding-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-works-list .work-actions .van-button {
|
||||||
|
height: 30px;
|
||||||
|
padding: 0 9px;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div id="app" v-cloak>
|
||||||
|
<van-nav-bar title="我的作品" left-arrow fixed placeholder @click-left="historyBack"></van-nav-bar>
|
||||||
|
|
||||||
|
<van-list v-model="loading" class="my-works-list" :finished="finished" :error.sync="failed"
|
||||||
|
error-text="加载失败,点击重试" style="min-height: calc(100vh - 46px)" @load="loadWorks">
|
||||||
|
<article v-for="work in works" :key="work.id" class="work-card">
|
||||||
|
<div class="work-summary">
|
||||||
|
<div class="work-cover">
|
||||||
|
<van-image v-if="work.activityCover" :src="work.activityCover" width="100%" height="100%" fit="cover"></van-image>
|
||||||
|
<van-icon v-else name="photo-o" size="24"></van-icon>
|
||||||
|
</div>
|
||||||
|
<div class="work-heading">
|
||||||
|
<h2 class="work-title" :title="work.activityName">{{ work.activityName || '—' }}</h2>
|
||||||
|
<div class="work-name" :title="work.name">作品名称:{{ work.name || '—' }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="work-metadata">
|
||||||
|
<div class="work-metadata-item">
|
||||||
|
<van-icon name="label-o" size="16"></van-icon>
|
||||||
|
<div>
|
||||||
|
<div>主题类型</div>
|
||||||
|
<div class="work-metadata-value">{{ work.subjectName || '—' }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="work-metadata-item">
|
||||||
|
<van-icon name="apps-o" size="16"></van-icon>
|
||||||
|
<div>
|
||||||
|
<div>作品类型</div>
|
||||||
|
<div class="work-metadata-value">{{ work.worksName || '—' }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="work-metadata-item">
|
||||||
|
<van-icon name="calendar-o" size="16"></van-icon>
|
||||||
|
<div>
|
||||||
|
<div>提交日期</div>
|
||||||
|
<div class="work-metadata-value">{{ work.createdAt ? $moment(work.createdAt).format('YYYY-MM-DD') : '—' }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<transition name="work-detail">
|
||||||
|
<div v-if="openWorks.includes(work.id)" :id="'work-detail-' + work.id" class="work-detail">
|
||||||
|
<div class="work-field">
|
||||||
|
<span class="work-field-label">作品描述</span>
|
||||||
|
<span class="work-field-value">{{ work.description || '—' }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="work-field">
|
||||||
|
<span class="work-field-label">收货地址</span>
|
||||||
|
<span class="work-field-value">{{ work.shippingAddress || '—' }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="work-field">
|
||||||
|
<span class="work-field-label">作品附件</span>
|
||||||
|
<div class="work-field-value">
|
||||||
|
<file-preview :files="work.files" complete_result></file-preview>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="Number(work.canModify) === 1" class="work-actions">
|
||||||
|
<van-button size="small" type="danger" plain icon="delete-o" :disabled="deleting"
|
||||||
|
@click="deleteWork(work)">删除</van-button>
|
||||||
|
<van-button size="small" type="primary" icon="edit" :disabled="deleting"
|
||||||
|
@click="editWork(work)">编辑</van-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
|
<button class="work-more" type="button" :aria-expanded="openWorks.includes(work.id) ? 'true' : 'false'"
|
||||||
|
:aria-controls="openWorks.includes(work.id) ? 'work-detail-' + work.id : null" @click="toggleWork(work.id)">
|
||||||
|
{{ openWorks.includes(work.id) ? '收起' : '查看更多' }}
|
||||||
|
</button>
|
||||||
|
</article>
|
||||||
|
<van-empty v-if="finished && !works.length" image="/assets/platform/plugins/vant-green/images/nodata/nodata.png"
|
||||||
|
description="暂无提交的作品"></van-empty>
|
||||||
|
</van-list>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
new Vue({
|
||||||
|
el: "#app",
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
moduleUrl: "/platform/h5/activity/worksCollection",
|
||||||
|
works: [],
|
||||||
|
openWorks: [],
|
||||||
|
pageNumber: 1,
|
||||||
|
loading: false,
|
||||||
|
finished: false,
|
||||||
|
failed: false,
|
||||||
|
deleting: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
toggleWork(id) {
|
||||||
|
const index = this.openWorks.indexOf(id)
|
||||||
|
if (index === -1) {
|
||||||
|
this.openWorks.push(id)
|
||||||
|
} else {
|
||||||
|
this.openWorks.splice(index, 1)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async loadWorks() {
|
||||||
|
try {
|
||||||
|
const { data } = await this.$axios.post(this.moduleUrl + "/minePageData", {
|
||||||
|
pageNumber: this.pageNumber,
|
||||||
|
pageSize: 10
|
||||||
|
})
|
||||||
|
const rows = data.list || []
|
||||||
|
this.works = this.works.concat(rows)
|
||||||
|
this.finished = !rows.length || this.pageNumber >= data.totalPage
|
||||||
|
this.pageNumber++
|
||||||
|
} catch (error) {
|
||||||
|
this.failed = true
|
||||||
|
} finally {
|
||||||
|
this.loading = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
editWork(work) {
|
||||||
|
if (Number(work.canModify) !== 1) return
|
||||||
|
this.$pjaxReplace(this.moduleUrl + "/upload?activityId=" + encodeURIComponent(work.activityId)
|
||||||
|
+ "&id=" + encodeURIComponent(work.id))
|
||||||
|
},
|
||||||
|
async deleteWork(work) {
|
||||||
|
if (this.deleting || this.loading || Number(work.canModify) !== 1) return
|
||||||
|
this.deleting = true
|
||||||
|
try {
|
||||||
|
await this.$dialog.confirm({ message: "确定删除这件作品吗?" })
|
||||||
|
await this.$axios.post(this.moduleUrl + "/deleteWork", { id: work.id })
|
||||||
|
this.works = []
|
||||||
|
this.openWorks = []
|
||||||
|
this.pageNumber = 1
|
||||||
|
this.finished = false
|
||||||
|
this.failed = false
|
||||||
|
this.loading = true
|
||||||
|
await this.loadWorks()
|
||||||
|
this.$toast.success("删除成功")
|
||||||
|
} catch (error) {
|
||||||
|
// 请求失败由公共响应处理显示。
|
||||||
|
} finally {
|
||||||
|
this.deleting = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!--#
|
||||||
|
}
|
||||||
|
#-->
|
||||||
|
|||||||
Reference in New Issue
Block a user