up
@ -14,7 +14,7 @@ export function getAliappConfig() {
|
||||
* @returns
|
||||
*/
|
||||
export function setAliappConfig(params: Record<string, any>) {
|
||||
return request.put('aliapp/config', params, {showSuccessMessage: true})
|
||||
return request.put('aliapp/config', params, { showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -6,7 +6,7 @@ import request from '@/utils/request'
|
||||
* @param app_type
|
||||
*/
|
||||
export function login(params: Record<string, any>, app_type: string) {
|
||||
return request.get(`login/${app_type}`, {params})
|
||||
return request.get(`login/${ app_type }`, { params })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -21,7 +21,7 @@ export function logout() {
|
||||
* @returns
|
||||
*/
|
||||
export function getAuthMenus(params: Record<string, any>) {
|
||||
return request.get('auth/authmenu', {params})
|
||||
return request.get('auth/authmenu', { params })
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -8,7 +8,7 @@ import request from '@/utils/request'
|
||||
* @returns
|
||||
*/
|
||||
export function getDiyPageList(params: Record<string, any>) {
|
||||
return request.get(`diy/diy`, {params})
|
||||
return request.get(`diy/diy`, { params })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -17,7 +17,7 @@ export function getDiyPageList(params: Record<string, any>) {
|
||||
* @returns
|
||||
*/
|
||||
export function getDiyPageListByCarouselSearch(params: Record<string, any>) {
|
||||
return request.get(`diy/carousel_search`, {params})
|
||||
return request.get(`diy/carousel_search`, { params })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -26,7 +26,7 @@ export function getDiyPageListByCarouselSearch(params: Record<string, any>) {
|
||||
* @returns
|
||||
*/
|
||||
export function getDiyList(params: Record<string, any>) {
|
||||
return request.get(`diy/list`, {params})
|
||||
return request.get(`diy/list`, { params })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -35,7 +35,7 @@ export function getDiyList(params: Record<string, any>) {
|
||||
* @returns
|
||||
*/
|
||||
export function getDiyPageInfo(id: number) {
|
||||
return request.get(`diy/diy/${id}`);
|
||||
return request.get(`diy/diy/${ id }`);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -44,7 +44,7 @@ export function getDiyPageInfo(id: number) {
|
||||
* @returns
|
||||
*/
|
||||
export function addDiyPage(params: Record<string, any>) {
|
||||
return request.post('diy/diy', params, {showSuccessMessage: true})
|
||||
return request.post('diy/diy', params, { showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -52,7 +52,7 @@ export function addDiyPage(params: Record<string, any>) {
|
||||
* @param params
|
||||
*/
|
||||
export function editDiyPage(params: Record<string, any>) {
|
||||
return request.put(`diy/diy/${params.id}`, params, {showSuccessMessage: true})
|
||||
return request.put(`diy/diy/${ params.id }`, params, { showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -60,7 +60,7 @@ export function editDiyPage(params: Record<string, any>) {
|
||||
* @param params
|
||||
*/
|
||||
export function setUseDiyPage(params: Record<string, any>) {
|
||||
return request.put(`diy/use/${params.id}`, params, {showSuccessMessage: true})
|
||||
return request.put(`diy/use/${ params.id }`, params, { showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -68,7 +68,7 @@ export function setUseDiyPage(params: Record<string, any>) {
|
||||
* @param params
|
||||
*/
|
||||
export function editDiyPageShare(params: Record<string, any>) {
|
||||
return request.put(`diy/diy/share`, params, {showSuccessMessage: true})
|
||||
return request.put(`diy/diy/share`, params, { showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -77,35 +77,35 @@ export function editDiyPageShare(params: Record<string, any>) {
|
||||
* @returns
|
||||
*/
|
||||
export function deleteDiyPage(id: number) {
|
||||
return request.delete(`diy/diy/${id}`, {showSuccessMessage: true})
|
||||
return request.delete(`diy/diy/${ id }`, { showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取自定义页面初始化数据
|
||||
*/
|
||||
export function initPage(params: Record<string, any>) {
|
||||
return request.get(`diy/init`, {params})
|
||||
return request.get(`diy/init`, { params })
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取自定义链接列表
|
||||
*/
|
||||
export function getLink(params: Record<string, any>) {
|
||||
return request.get(`diy/link`, {params})
|
||||
return request.get(`diy/link`, { params })
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取底部导航列表
|
||||
*/
|
||||
export function getDiyBottomList(params: Record<string, any>) {
|
||||
return request.get(`diy/bottom`, {params})
|
||||
return request.get(`diy/bottom`, { params })
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取底部导航数据
|
||||
*/
|
||||
export function getDiyBottomConfig(params: Record<string, any>) {
|
||||
return request.get(`diy/bottom/config`, {params})
|
||||
return request.get(`diy/bottom/config`, { params })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -114,21 +114,21 @@ export function getDiyBottomConfig(params: Record<string, any>) {
|
||||
* @returns
|
||||
*/
|
||||
export function setDiyBottomConfig(params: Record<string, any>) {
|
||||
return request.post('diy/bottom', params, {showSuccessMessage: true})
|
||||
return request.post('diy/bottom', params, { showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取页面模板类型
|
||||
*/
|
||||
export function getDiyTemplate(params: Record<string, any>) {
|
||||
return request.get(`diy/template`, {params})
|
||||
return request.get(`diy/template`, { params })
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取模板页面列表
|
||||
*/
|
||||
export function getDiyTemplatePages(params: Record<string, any>) {
|
||||
return request.get(`diy/template/pages`, {params})
|
||||
return request.get(`diy/template/pages`, { params })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -137,7 +137,7 @@ export function getDiyTemplatePages(params: Record<string, any>) {
|
||||
* @returns
|
||||
*/
|
||||
export function getDiyRouteList(params: Record<string, any>) {
|
||||
return request.get(`diy/route`, {params})
|
||||
return request.get(`diy/route`, { params })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -145,7 +145,7 @@ export function getDiyRouteList(params: Record<string, any>) {
|
||||
* @returns
|
||||
*/
|
||||
export function getDiyRouteAppList() {
|
||||
return request.get(`diy/route/apps`)
|
||||
return request.get(`diy/route/apps`)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -153,7 +153,7 @@ export function getDiyRouteAppList() {
|
||||
* @param params
|
||||
*/
|
||||
export function getDiyRouteInfo(params: Record<string, any>) {
|
||||
return request.get(`diy/route/info`, {params});
|
||||
return request.get(`diy/route/info`, { params });
|
||||
}
|
||||
|
||||
/**
|
||||
@ -161,7 +161,7 @@ export function getDiyRouteInfo(params: Record<string, any>) {
|
||||
* @param params
|
||||
*/
|
||||
export function editDiyRouteShare(params: Record<string, any>) {
|
||||
return request.put(`diy/route/share`, params, {showSuccessMessage: true})
|
||||
return request.put(`diy/route/share`, params, { showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -170,7 +170,7 @@ export function editDiyRouteShare(params: Record<string, any>) {
|
||||
* @returns
|
||||
*/
|
||||
export function getDecoratePage(params: Record<string, any>) {
|
||||
return request.get(`diy/decorate`, {params})
|
||||
return request.get(`diy/decorate`, { params })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -179,7 +179,7 @@ export function getDecoratePage(params: Record<string, any>) {
|
||||
* @returns
|
||||
*/
|
||||
export function changeTemplate(params: Record<string, any>) {
|
||||
return request.put(`diy/change`, params, {showSuccessMessage: true})
|
||||
return request.put(`diy/change`, params, { showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -188,7 +188,7 @@ export function changeTemplate(params: Record<string, any>) {
|
||||
* @returns
|
||||
*/
|
||||
export function getApps(params: Record<string, any>) {
|
||||
return request.get(`diy/apps`)
|
||||
return request.get(`diy/apps`)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -207,7 +207,7 @@ export function copyDiy(params: Record<string, any>) {
|
||||
* @param params
|
||||
*/
|
||||
export function getDefaultTheme(params: Record<string, any>) {
|
||||
return request.get(`diy/theme/color`, {params})
|
||||
return request.get(`diy/theme/color`, { params })
|
||||
}
|
||||
|
||||
|
||||
@ -216,7 +216,7 @@ export function getDefaultTheme(params: Record<string, any>) {
|
||||
* @param params
|
||||
*/
|
||||
export function getDiyTheme(params: Record<string, any>) {
|
||||
return request.get(`diy/theme`, {params})
|
||||
return request.get(`diy/theme`, { params })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -232,7 +232,7 @@ export function addTheme(params: Record<string, any>) {
|
||||
* @param params
|
||||
*/
|
||||
export function editTheme(params: Record<string, any>) {
|
||||
return request.put(`diy/theme/edit/${params.id}`, params, {showSuccessMessage: true})
|
||||
return request.put(`diy/theme/edit/${ params.id }`, params, { showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -240,13 +240,13 @@ export function editTheme(params: Record<string, any>) {
|
||||
* @param params
|
||||
*/
|
||||
export function deleteTheme(id: number) {
|
||||
return request.delete(`diy/theme/delete/${id}`, {showSuccessMessage: true})
|
||||
return request.delete(`diy/theme/delete/${ id }`, { showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置主题配色
|
||||
* 设置主题配色
|
||||
* @param params
|
||||
*/
|
||||
export function setDiyTheme(params: Record<string, any>) {
|
||||
return request.post(`diy/theme`, params, { showSuccessMessage: true })
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,6 +19,7 @@ export function getDiyFormPageList(params: Record<string, any>) {
|
||||
export function getDiyFormList(params: Record<string, any>) {
|
||||
return request.get(`diy/form/list`, { params })
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取万能表单分页列表(用于弹框选择)
|
||||
* @param params
|
||||
|
||||
@ -11,7 +11,7 @@ export function getAuthInfo() {
|
||||
* 设置 授权配置
|
||||
*/
|
||||
export function setAuthInfo(params: Record<string, any>) {
|
||||
return request.post('niucloud/authinfo', params, {showSuccessMessage: true})
|
||||
return request.post('niucloud/authinfo', params, { showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -43,7 +43,7 @@ export function getModuleVersion() {
|
||||
* @returns
|
||||
*/
|
||||
export function downloadVersion(params: Record<string, any>) {
|
||||
return request.post(`addon/download/${params.addon}`, params, { showSuccessMessage: true })
|
||||
return request.post(`addon/download/${ params.addon }`, params, { showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -61,3 +61,11 @@ export function getFrameworkNewVersion() {
|
||||
export function getFrameworkVersionList() {
|
||||
return request.get(`niucloud/framework/version/list`)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取应用/插件的版本更新记录
|
||||
* @param params
|
||||
*/
|
||||
export function getAppVersionList(params: Record<string, any>) {
|
||||
return request.get(`niucloud/app_version/list`, { params })
|
||||
}
|
||||
|
||||
@ -7,7 +7,7 @@ import request from '@/utils/request'
|
||||
* @returns
|
||||
*/
|
||||
export function getNoticeList(params: any) {
|
||||
return request.get('notice/notice', {params})
|
||||
return request.get('notice/notice', { params })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -16,7 +16,7 @@ export function getNoticeList(params: any) {
|
||||
* @returns
|
||||
*/
|
||||
export function getNoticeLog(params: any) {
|
||||
return request.get(`notice/log`, {params})
|
||||
return request.get(`notice/log`, { params })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -25,7 +25,7 @@ export function getNoticeLog(params: any) {
|
||||
* @returns
|
||||
*/
|
||||
export function getNoticeInfo(key: string) {
|
||||
return request.get(`notice/notice/${key}`)
|
||||
return request.get(`notice/notice/${ key }`)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -34,7 +34,7 @@ export function getNoticeInfo(key: string) {
|
||||
* @returns
|
||||
*/
|
||||
export function editNoticeStatus(params: Record<string, any>) {
|
||||
return request.post(`notice/notice/editstatus`, params, {showSuccessMessage: true})
|
||||
return request.post(`notice/notice/editstatus`, params, { showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -43,7 +43,7 @@ export function editNoticeStatus(params: Record<string, any>) {
|
||||
* @returns
|
||||
*/
|
||||
export function editNotice(params: Record<string, any>) {
|
||||
return request.post(`notice/notice/edit`, params, {showSuccessMessage: true})
|
||||
return request.post(`notice/notice/edit`, params, { showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -60,7 +60,7 @@ export function getSmsList() {
|
||||
* @returns
|
||||
*/
|
||||
export function getSmsInfo(sms_type: string) {
|
||||
return request.get(`notice/notice/sms/${sms_type}`,)
|
||||
return request.get(`notice/notice/sms/${ sms_type }`,)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -68,7 +68,7 @@ export function getSmsInfo(sms_type: string) {
|
||||
* @param params
|
||||
*/
|
||||
export function editSms(params: Record<string, any>) {
|
||||
return request.put(`notice/notice/sms/${params.sms_type}`, params, {showSuccessMessage: true})
|
||||
return request.put(`notice/notice/sms/${ params.sms_type }`, params, { showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -54,6 +54,14 @@ export function getPayRefundInfo(refund_no: string) {
|
||||
return request.get(`pay/refund/${refund_no}`)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取退款状态字典
|
||||
* @param refund_no
|
||||
*/
|
||||
export function getRefundStatus() {
|
||||
return request.get(`pay/refund/status`)
|
||||
}
|
||||
|
||||
/**
|
||||
* 退款方式
|
||||
*/
|
||||
|
||||
@ -14,5 +14,5 @@ export function getPcConfig() {
|
||||
* @returns
|
||||
*/
|
||||
export function setPcConfig(params: Record<string, any>) {
|
||||
return request.put('channel/pc/config', params, {showSuccessMessage: true})
|
||||
return request.put('channel/pc/config', params, { showSuccessMessage: true })
|
||||
}
|
||||
|
||||
@ -13,6 +13,6 @@ export function getUserInfo() {
|
||||
* @returns
|
||||
*/
|
||||
export function setUserInfo(params: Record<string, any>) {
|
||||
return request.put(`auth/edit`, params, {showSuccessMessage: true});
|
||||
return request.put(`auth/edit`, params, { showSuccessMessage: true });
|
||||
}
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@ import request from '@/utils/request'
|
||||
* @returns
|
||||
*/
|
||||
export function getPosterPageList(params: Record<string, any>) {
|
||||
return request.get(`sys/poster`, {params})
|
||||
return request.get(`sys/poster`, { params })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -15,7 +15,7 @@ export function getPosterPageList(params: Record<string, any>) {
|
||||
* @returns
|
||||
*/
|
||||
export function getPosterList(params: Record<string, any>) {
|
||||
return request.get(`sys/poster/list`, {params})
|
||||
return request.get(`sys/poster/list`, { params })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -24,7 +24,7 @@ export function getPosterList(params: Record<string, any>) {
|
||||
* @returns
|
||||
*/
|
||||
export function getPosterInfo(id: number) {
|
||||
return request.get(`sys/poster/${id}`);
|
||||
return request.get(`sys/poster/${ id }`);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -33,7 +33,7 @@ export function getPosterInfo(id: number) {
|
||||
* @returns
|
||||
*/
|
||||
export function addPoster(params: Record<string, any>) {
|
||||
return request.post('sys/poster', params, {showErrorMessage: true, showSuccessMessage: true})
|
||||
return request.post('sys/poster', params, { showErrorMessage: true, showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -42,7 +42,7 @@ export function addPoster(params: Record<string, any>) {
|
||||
* @returns
|
||||
*/
|
||||
export function editPoster(params: Record<string, any>) {
|
||||
return request.put(`sys/poster/${params.id}`, params, {
|
||||
return request.put(`sys/poster/${ params.id }`, params, {
|
||||
showErrorMessage: true,
|
||||
showSuccessMessage: true
|
||||
})
|
||||
@ -54,7 +54,7 @@ export function editPoster(params: Record<string, any>) {
|
||||
* @returns
|
||||
*/
|
||||
export function deletePoster(id: number) {
|
||||
return request.delete(`sys/poster/${id}`, {showErrorMessage: true, showSuccessMessage: true})
|
||||
return request.delete(`sys/poster/${ id }`, { showErrorMessage: true, showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -62,7 +62,7 @@ export function deletePoster(id: number) {
|
||||
* @param params
|
||||
*/
|
||||
export function modifyPosterStatus(params: Record<string, any>) {
|
||||
return request.put(`sys/poster/status`, params, {showSuccessMessage: true})
|
||||
return request.put(`sys/poster/status`, params, { showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -70,7 +70,7 @@ export function modifyPosterStatus(params: Record<string, any>) {
|
||||
* @param params
|
||||
*/
|
||||
export function modifyPosterDefault(params: Record<string, any>) {
|
||||
return request.put(`sys/poster/default`, params, {showSuccessMessage: true})
|
||||
return request.put(`sys/poster/default`, params, { showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -79,7 +79,7 @@ export function modifyPosterDefault(params: Record<string, any>) {
|
||||
* @returns
|
||||
*/
|
||||
export function getPosterType(params: Record<string, any>) {
|
||||
return request.get(`sys/poster/type`, {params})
|
||||
return request.get(`sys/poster/type`, { params })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -88,21 +88,21 @@ export function getPosterType(params: Record<string, any>) {
|
||||
* @returns
|
||||
*/
|
||||
export function getPosterTemplate(params: Record<string, any>) {
|
||||
return request.get(`sys/poster/template`, {params})
|
||||
return request.get(`sys/poster/template`, { params })
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取自定义海报初始化数据
|
||||
*/
|
||||
export function initPoster(params: Record<string, any>) {
|
||||
return request.get(`sys/poster/init`, {params})
|
||||
return request.get(`sys/poster/init`, { params })
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取自定义海报预览
|
||||
*/
|
||||
export function getPreviewPoster(params: Record<string, any>) {
|
||||
return request.get(`sys/poster/preview`, {params})
|
||||
return request.get(`sys/poster/preview`, { params })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -111,5 +111,5 @@ export function getPreviewPoster(params: Record<string, any>) {
|
||||
* @returns
|
||||
*/
|
||||
export function getPosterGenerate(params: Record<string, any>) {
|
||||
return request.get(`sys/poster/generate`, {params, showErrorMessage: false})
|
||||
}
|
||||
return request.get(`sys/poster/generate`, { params, showErrorMessage: false })
|
||||
}
|
||||
|
||||
@ -18,7 +18,7 @@ export function getSiteList(params: Record<string, any>) {
|
||||
* @param site_id
|
||||
*/
|
||||
export function getSiteInfo(site_id: number) {
|
||||
return request.get(`site/site/${site_id}`);
|
||||
return request.get(`site/site/${ site_id }`);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -35,7 +35,7 @@ export function addSite(params: Record<string, any>) {
|
||||
* @param params
|
||||
*/
|
||||
export function editSite(params: Record<string, any>) {
|
||||
return request.put(`site/site/${params.site_id}`, params, { showSuccessMessage: true })
|
||||
return request.put(`site/site/${ params.site_id }`, params, { showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -43,7 +43,7 @@ export function editSite(params: Record<string, any>) {
|
||||
* @param siteId
|
||||
*/
|
||||
export function deleteSite(siteId: number) {
|
||||
return request.delete(`site/site/${siteId}`)
|
||||
return request.delete(`site/site/${ siteId }`)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -51,7 +51,7 @@ export function deleteSite(siteId: number) {
|
||||
* @param params
|
||||
*/
|
||||
export function closeSite(params: Record<string, any>) {
|
||||
return request.put(`site/closesite/${params.site_id}`, params, { showSuccessMessage: true })
|
||||
return request.put(`site/closesite/${ params.site_id }`, params, { showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -59,7 +59,7 @@ export function closeSite(params: Record<string, any>) {
|
||||
* @param params
|
||||
*/
|
||||
export function openSite(params: Record<string, any>) {
|
||||
return request.put(`site/opensite/${params.site_id}`, params, { showSuccessMessage: true })
|
||||
return request.put(`site/opensite/${ params.site_id }`, params, { showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -85,7 +85,7 @@ export function getSiteGroupList(params: Record<string, any>) {
|
||||
* @param groupId
|
||||
*/
|
||||
export function getSiteGroupInfo(groupId: number) {
|
||||
return request.get(`site/group/${groupId}`);
|
||||
return request.get(`site/group/${ groupId }`);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -102,7 +102,7 @@ export function addSiteGroup(params: Record<string, any>) {
|
||||
* @param params
|
||||
*/
|
||||
export function editSiteGroup(params: Record<string, any>) {
|
||||
return request.put(`site/group/${params.group_id}`, params, { showSuccessMessage: true })
|
||||
return request.put(`site/group/${ params.group_id }`, params, { showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -110,7 +110,7 @@ export function editSiteGroup(params: Record<string, any>) {
|
||||
* @param group_id
|
||||
*/
|
||||
export function deleteSiteGroup(group_id: number) {
|
||||
return request.delete(`site/group/${group_id}`, { showSuccessMessage: true });
|
||||
return request.delete(`site/group/${ group_id }`, { showSuccessMessage: true });
|
||||
}
|
||||
|
||||
/**
|
||||
@ -146,7 +146,7 @@ export function getUserList(params: Record<string, any>) {
|
||||
* @param uid
|
||||
*/
|
||||
export function getUserInfo(uid: number) {
|
||||
return request.get(`site/user/${uid}`);
|
||||
return request.get(`site/user/${ uid }`);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -163,7 +163,7 @@ export function addUser(params: Record<string, any>) {
|
||||
* @param params
|
||||
*/
|
||||
export function editUser(params: Record<string, any>) {
|
||||
return request.put(`site/user/${params.uid}`, params, { showSuccessMessage: true })
|
||||
return request.put(`site/user/${ params.uid }`, params, { showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -172,7 +172,7 @@ export function editUser(params: Record<string, any>) {
|
||||
* @returns
|
||||
*/
|
||||
export function lockUser(uid: number) {
|
||||
return request.put(`site/user/lock/${uid}`)
|
||||
return request.put(`site/user/lock/${ uid }`)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -181,7 +181,7 @@ export function lockUser(uid: number) {
|
||||
* @returns
|
||||
*/
|
||||
export function unlockUser(uid: number) {
|
||||
return request.put(`site/user/unlock/${uid}`)
|
||||
return request.put(`site/user/unlock/${ uid }`)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -190,7 +190,7 @@ export function unlockUser(uid: number) {
|
||||
* @param uid
|
||||
*/
|
||||
export function deleteUser(uid: number) {
|
||||
return request.delete(`site/user/${uid}`)
|
||||
return request.delete(`site/user/${ uid }`)
|
||||
}
|
||||
|
||||
/***************************************************** 操作日志 **************************************************/
|
||||
@ -209,7 +209,7 @@ export function getLogList(params: Record<string, any>) {
|
||||
* @param id
|
||||
*/
|
||||
export function getLogInfo(id: number) {
|
||||
return request.get(`site/log/${id}`)
|
||||
return request.get(`site/log/${ id }`)
|
||||
}
|
||||
|
||||
/***************************************************** 账单列表 **************************************************/
|
||||
@ -228,7 +228,7 @@ export function getAccountList(params: Record<string, any>) {
|
||||
* @param id
|
||||
*/
|
||||
export function getAccountInfo(id: number) {
|
||||
return request.get(`site/account/${id}`)
|
||||
return request.get(`site/account/${ id }`)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -788,3 +788,11 @@ export function deleteExport(id: number) {
|
||||
export function getWxoplatform() {
|
||||
return request.get('sys/wxoplatform/config')
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取二维码
|
||||
* @returns
|
||||
*/
|
||||
export function getQrcode(params: Record<string, any>) {
|
||||
return request.get(`sys/qrcode`, { params, showErrorMessage: false })
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@ import request from '@/utils/request'
|
||||
* @returns
|
||||
*/
|
||||
export function getAddonDevelop(params: Record<string, any>) {
|
||||
return request.get(`addon_develop`, {params});
|
||||
return request.get(`addon_develop`, { params });
|
||||
}
|
||||
|
||||
/**
|
||||
@ -22,7 +22,7 @@ export function getAddontype() {
|
||||
* @returns
|
||||
*/
|
||||
export function getAddonDevelopInfo(key: any) {
|
||||
return request.get(`addon_develop/${key}`)
|
||||
return request.get(`addon_develop/${ key }`)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -30,7 +30,7 @@ export function getAddonDevelopInfo(key: any) {
|
||||
* @returns
|
||||
*/
|
||||
export function getAddonDevelopCheck(key: any) {
|
||||
return request.get(`addon_develop/check/${key}`)
|
||||
return request.get(`addon_develop/check/${ key }`)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -48,7 +48,7 @@ export function getAddonKeyBlackList() {
|
||||
* @returns
|
||||
*/
|
||||
export function addAddonDevelop(key: any, params: Record<string, any>) {
|
||||
return request.post(`addon_develop/${key}`, params)
|
||||
return request.post(`addon_develop/${ key }`, params)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -58,7 +58,7 @@ export function addAddonDevelop(key: any, params: Record<string, any>) {
|
||||
* @returns
|
||||
*/
|
||||
export function editAddonDevelop(key: any, params: Record<string, any>) {
|
||||
return request.put(`addon_develop/${key}`, params)
|
||||
return request.put(`addon_develop/${ key }`, params)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -67,7 +67,7 @@ export function editAddonDevelop(key: any, params: Record<string, any>) {
|
||||
* @returns
|
||||
*/
|
||||
export function deleteAddonDevelop(key: any) {
|
||||
return request.delete(`addon_develop/${key}`, {showSuccessMessage: true})
|
||||
return request.delete(`addon_develop/${ key }`, { showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -75,7 +75,7 @@ export function deleteAddonDevelop(key: any) {
|
||||
* @returns
|
||||
*/
|
||||
export function addonDevelopBuild(key: any) {
|
||||
return request.post(`addon_develop/build/${key}`)
|
||||
return request.post(`addon_develop/build/${ key }`)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -83,8 +83,9 @@ export function addonDevelopBuild(key: any) {
|
||||
* @returns
|
||||
*/
|
||||
export function addonDevelopDownload(key: any) {
|
||||
return request.post(`addon_develop/download/${key}`, {})
|
||||
return request.post(`addon_develop/download/${ key }`, {})
|
||||
}
|
||||
|
||||
/***************************************************** 代码生成 ****************************************************/
|
||||
|
||||
/**
|
||||
@ -93,7 +94,7 @@ export function addonDevelopDownload(key: any) {
|
||||
* @returns
|
||||
*/
|
||||
export function getGenerateTableList(params: Record<string, any>) {
|
||||
return request.get(`generator/generator`, {params})
|
||||
return request.get(`generator/generator`, { params })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -102,7 +103,7 @@ export function getGenerateTableList(params: Record<string, any>) {
|
||||
* @returns
|
||||
*/
|
||||
export function getGenerateTableInfo(id: number) {
|
||||
return request.get(`generator/generator/${id}`);
|
||||
return request.get(`generator/generator/${ id }`);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -111,7 +112,7 @@ export function getGenerateTableInfo(id: number) {
|
||||
* @returns
|
||||
*/
|
||||
export function addGenerateTable(params: Record<string, any>) {
|
||||
return request.post('generator/generator', params, {showSuccessMessage: true})
|
||||
return request.post('generator/generator', params, { showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -119,7 +120,7 @@ export function addGenerateTable(params: Record<string, any>) {
|
||||
* @param params
|
||||
*/
|
||||
export function editGenerateTable(params: Record<string, any>) {
|
||||
return request.put(`generator/generator/${params.id}`, params, {showSuccessMessage: true})
|
||||
return request.put(`generator/generator/${ params.id }`, params, { showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -128,7 +129,7 @@ export function editGenerateTable(params: Record<string, any>) {
|
||||
* @returns
|
||||
*/
|
||||
export function deleteGenerateTable(id: number) {
|
||||
return request.delete(`generator/generator/${id}`, {showSuccessMessage: true})
|
||||
return request.delete(`generator/generator/${ id }`, { showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -146,7 +147,7 @@ export function generateCreate(params: Record<string, any>) {
|
||||
* @returns
|
||||
*/
|
||||
export function generatePreview(id: number) {
|
||||
return request.get(`generator/preview/${id}`)
|
||||
return request.get(`generator/preview/${ id }`)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -167,26 +168,26 @@ export function getSystem() {
|
||||
* 获取全部模型
|
||||
*/
|
||||
export function getGeneratorAllModel(params: any) {
|
||||
return request.get(`generator/all_model`, {params})
|
||||
return request.get(`generator/all_model`, { params })
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 表字段
|
||||
*/
|
||||
export function getGeneratorTableColumn(params: any) {
|
||||
return request.get(`generator/table_column`, {params})
|
||||
return request.get(`generator/table_column`, { params })
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步校验
|
||||
*/
|
||||
export function generatorCheckFile(params: Record<string, any>) {
|
||||
return request.get(`generator/check_file`, {params})
|
||||
return request.get(`generator/check_file`, { params })
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据模型获取表字段
|
||||
*/
|
||||
export function getGeneratorModelTableColumn(params: any) {
|
||||
return request.get(`generator/model_table_column`, {params})
|
||||
return request.get(`generator/model_table_column`, { params })
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@ import request from '@/utils/request'
|
||||
* @param addon
|
||||
*/
|
||||
export function getUpgradeContent(addon: string = '') {
|
||||
return request.get(addon ? `upgrade/${addon}` : 'upgrade')
|
||||
return request.get(addon ? `upgrade/${ addon }` : 'upgrade')
|
||||
}
|
||||
|
||||
/**
|
||||
@ -21,21 +21,21 @@ export function getUpgradeTask() {
|
||||
* @param addon
|
||||
*/
|
||||
export function upgradeAddon(addon: string = '') {
|
||||
return request.post(addon ? `upgrade/${addon}` : 'upgrade')
|
||||
return request.post(addon ? `upgrade/${ addon }` : 'upgrade')
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行升级
|
||||
*/
|
||||
export function executeUpgrade() {
|
||||
return request.post('upgrade/execute', {})
|
||||
return request.post('upgrade/execute', {}, { showErrorMessage: false })
|
||||
}
|
||||
|
||||
/**
|
||||
* 升级前检测
|
||||
*/
|
||||
export function preUpgradeCheck(addon: string = '') {
|
||||
return request.get(addon ? `upgrade/check/${addon}` : 'upgrade/check')
|
||||
return request.get(addon ? `upgrade/check/${ addon }` : 'upgrade/check')
|
||||
}
|
||||
|
||||
/**
|
||||
@ -44,3 +44,88 @@ export function preUpgradeCheck(addon: string = '') {
|
||||
export function clearUpgradeTask() {
|
||||
return request.post('upgrade/clear')
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户操作
|
||||
* @param operate
|
||||
*/
|
||||
export function upgradeUserOperate(operate: string) {
|
||||
return request.post(`upgrade/operate/${ operate }`)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取升级记录分页列表
|
||||
* @param params
|
||||
* @returns
|
||||
*/
|
||||
export function getUpgradeRecords(params: Record<string, any>) {
|
||||
return request.get(`upgrade/records`, { params })
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取备份记录分页列表
|
||||
* @param params
|
||||
* @returns
|
||||
*/
|
||||
export function getBackupRecords(params: Record<string, any>) {
|
||||
return request.get(`backup/records`, { params })
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改备份备注
|
||||
* @param params
|
||||
*/
|
||||
export function modifyBackupRemark(params: Record<string, any>) {
|
||||
return request.put(`backup/remark`, params, { showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
* 备份功能 检测目录权限
|
||||
*/
|
||||
export function checkDirExist(params: Record<string, any>) {
|
||||
return request.post('backup/check_dir', params)
|
||||
}
|
||||
|
||||
/**
|
||||
* 备份功能 检测目录权限
|
||||
*/
|
||||
export function checkPermission(params: Record<string, any>) {
|
||||
return request.post('backup/check_permission', params)
|
||||
}
|
||||
|
||||
/**
|
||||
* 备份功能 恢复升级备份
|
||||
*/
|
||||
export function restoreUpgradeBackup(params: Record<string, any>) {
|
||||
return request.post('backup/restore', params)
|
||||
}
|
||||
|
||||
/**
|
||||
* 备份功能 删除升级记录
|
||||
*/
|
||||
export function deleteRecords(params: Record<string, any>) {
|
||||
return request.post('backup/delete', params, { showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
* 手动备份
|
||||
*/
|
||||
export function manualBackup(params: Record<string, any>) {
|
||||
return request.post("backup/manual", params)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取进行中的恢复
|
||||
* @param params
|
||||
*/
|
||||
export function performRecoveryTasks(params: Record<string, any>) {
|
||||
return request.get("backup/restore_task", params)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取进行中的备份
|
||||
* @param params
|
||||
*/
|
||||
export function performBackupTasks(params: Record<string, any>) {
|
||||
return request.get("backup/task", params)
|
||||
}
|
||||
@ -36,7 +36,7 @@ export function addUser(params: Record<string, any>) {
|
||||
* @param uid
|
||||
*/
|
||||
export function deleteUser(uid: number) {
|
||||
return request.delete(`user/user/${uid}`, { showSuccessMessage: true })
|
||||
return request.delete(`user/user/${ uid }`, { showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -44,7 +44,7 @@ export function deleteUser(uid: number) {
|
||||
* @param uid
|
||||
*/
|
||||
export function editUser(params: Record<string, any>) {
|
||||
return request.put(`user/user/${params.uid}`, params, { showSuccessMessage: true })
|
||||
return request.put(`user/user/${ params.uid }`, params, { showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -18,7 +18,7 @@ export function getVerifyRecord(params: Record<string, any>) {
|
||||
* @returns
|
||||
*/
|
||||
export function getVerifyDetail(verifyCode: string) {
|
||||
return request.get(`verify/verify/${verifyCode}`)
|
||||
return request.get(`verify/verify/${ verifyCode }`)
|
||||
}
|
||||
|
||||
/***************************************************** 核销员 ****************************************************/
|
||||
@ -64,5 +64,21 @@ export function addVerifier(params: Record<string, any>) {
|
||||
* @returns
|
||||
*/
|
||||
export function deleteVerifier(id: number) {
|
||||
return request.delete(`verify/verifier/${id}`, { showSuccessMessage: true })
|
||||
}
|
||||
return request.delete(`verify/verifier/${ id }`, { showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取核销员信息
|
||||
* @returns
|
||||
*/
|
||||
export function getVerifyInfo(id: number) {
|
||||
return request.get(`verify/verifier/${ id }`)
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改核销员信息
|
||||
* @returns
|
||||
*/
|
||||
export function editVerifier(params: Record<string, any>) {
|
||||
return request.post(`verify/verifier/${ params.id }`, params,{ showSuccessMessage: true })
|
||||
}
|
||||
|
||||
@ -33,6 +33,7 @@ export function getTemplateList() {
|
||||
export function getBatchAcquisition(params: Record<string, any>) {
|
||||
return request.put('weapp/template/sync', params, { showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加微信小程序版本
|
||||
* @param params
|
||||
@ -65,7 +66,7 @@ export function getWeappVersionList(params: Record<string, any>) {
|
||||
* @returns
|
||||
*/
|
||||
export function getWeappUploadLog(key: string) {
|
||||
return request.get(`weapp/upload/${key}`)
|
||||
return request.get(`weapp/upload/${ key }`)
|
||||
}
|
||||
|
||||
/***************************************************** 管理端 ****************************************************/
|
||||
@ -103,7 +104,7 @@ export function getVersionList(params: Record<string, any>) {
|
||||
* @returns
|
||||
*/
|
||||
export function getVersionInfo(id: string) {
|
||||
return request.get(`applet/version/${id}`)
|
||||
return request.get(`applet/version/${ id }`)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -112,7 +113,7 @@ export function getVersionInfo(id: string) {
|
||||
* @returns
|
||||
*/
|
||||
export function editVersion(params: Record<string, any>) {
|
||||
return request.put(`applet/version/${params.id}`, params, { showSuccessMessage: true })
|
||||
return request.put(`applet/version/${ params.id }`, params, { showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -121,7 +122,7 @@ export function editVersion(params: Record<string, any>) {
|
||||
* @returns
|
||||
*/
|
||||
export function deleteVersion(id: string) {
|
||||
return request.delete(`applet/version/${id}`)
|
||||
return request.delete(`applet/version/${ id }`)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -21,7 +21,7 @@ export function getWechatStatic() {
|
||||
* @returns
|
||||
*/
|
||||
export function editWechatConfig(params: Record<string, any>) {
|
||||
return request.put('wechat/config', params, {showSuccessMessage: true})
|
||||
return request.put('wechat/config', params, { showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -38,7 +38,7 @@ export function getWechatMenu() {
|
||||
* @returns
|
||||
*/
|
||||
export function editWechatMenu(params: Record<string, any>) {
|
||||
return request.put('wechat/menu', params, {showSuccessMessage: true})
|
||||
return request.put('wechat/menu', params, { showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -55,7 +55,7 @@ export function getTemplateList() {
|
||||
* @returns
|
||||
*/
|
||||
export function getBatchAcquisition(params: Record<string, any>) {
|
||||
return request.put('wechat/template/sync', params, {showSuccessMessage: true})
|
||||
return request.put('wechat/template/sync', params, { showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -69,7 +69,7 @@ export function getKeywordsReplyList(params: Record<string, any>) {
|
||||
* 修改关键字回复
|
||||
*/
|
||||
export function editKeywordsReply(params: Record<string, any>) {
|
||||
return request.put(`wechat/reply/keywords/${params.id}`, params, { showSuccessMessage: true })
|
||||
return request.put(`wechat/reply/keywords/${ params.id }`, params, { showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -84,14 +84,14 @@ export function addKeywordsReply(params: Record<string, any>) {
|
||||
* @param id
|
||||
*/
|
||||
export function getKeywordsReplyInfo(id: number) {
|
||||
return request.get(`wechat/reply/keywords/${id}`)
|
||||
return request.get(`wechat/reply/keywords/${ id }`)
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改关键字回复
|
||||
*/
|
||||
export function delKeywordsReply(id: number) {
|
||||
return request.delete(`wechat/reply/keywords/${id}`, { showSuccessMessage: true })
|
||||
return request.delete(`wechat/reply/keywords/${ id }`, { showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -42,8 +42,8 @@ export function getAuthorizationResult(params: Record<string, any>) {
|
||||
* 小程序代码提交
|
||||
* @returns
|
||||
*/
|
||||
export function weappCommit() {
|
||||
return request.post('wxoplatform/weapp/version/commit', {}, { showSuccessMessage: true })
|
||||
export function weappCommit(params: Record<string, any>) {
|
||||
return request.post('wxoplatform/weapp/version/commit', params, { showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -67,3 +67,11 @@ export function getWeappLastCommitRecord() {
|
||||
export function siteWeappCommit() {
|
||||
return request.post('wxoplatform/site/weapp/commit', {}, { showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
* 按站点套餐获取提交记录
|
||||
*/
|
||||
export function getSiteGroupCommitRecord(params: Record<string, any>) {
|
||||
return request.get('wxoplatform/sitegroup/commit', { params })
|
||||
}
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 80 KiB After Width: | Height: | Size: 74 KiB |
BIN
admin/src/app/assets/images/tools/tools_backup_records.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
admin/src/app/assets/images/tools/tools_cloud_compile.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
admin/src/app/assets/images/tools/tools_upgrade.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
admin/src/app/assets/images/tools/tools_upgrade_records.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
admin/src/app/assets/images/white_logo.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
@ -84,7 +84,6 @@ const active = ref('build')
|
||||
const cloudBuildCheck = ref<null | AnyObject>(null)
|
||||
const loading = ref(false)
|
||||
const terminalRef = ref(null)
|
||||
const emits = defineEmits(['complete'])
|
||||
|
||||
let cloudBuildLog = []
|
||||
/**
|
||||
@ -127,7 +126,7 @@ const getCloudBuildLogFn = () => {
|
||||
|
||||
data[0].forEach(item => {
|
||||
if (!cloudBuildLog.includes(item.action)) {
|
||||
terminalRef.value.pushMessage({ content: `正在执行:${item.action}` })
|
||||
terminalRef.value.pushMessage({ content: `${item.action}` })
|
||||
cloudBuildLog.push(item.action)
|
||||
|
||||
if (item.code == 0) {
|
||||
|
||||
239
admin/src/app/components/upgrade-log/index.vue
Normal file
@ -0,0 +1,239 @@
|
||||
<template>
|
||||
<el-dialog v-model="dialogVisible" :title="t('gxx')" width="850">
|
||||
<el-card class="box-card !border-none" shadow="never" >
|
||||
<div v-loading="loading">
|
||||
<div class="text-page-title mb-[20px]">历史版本</div>
|
||||
<div class="time-dialog h-[500px]" style="overflow: auto">
|
||||
<el-scrollbar>
|
||||
<el-timeline style="width: 100%" v-if="!loading">
|
||||
<el-timeline-item v-for="(item, index) in frameworkVersionList" :key="index" placement="left" :color="color">
|
||||
<div class="relative">
|
||||
<span class="text-[#333333] text-[14px] absolute">{{ timeSplit(item.release_time)[0] }}</span>
|
||||
<br />
|
||||
<span class="text-[#999999] text-[14px] w-[78px] block mt-[10px] absolute text-right">{{ timeSplit(item.release_time)[1] }}</span>
|
||||
</div>
|
||||
<el-collapse v-model="activeName" accordion>
|
||||
<el-collapse-item :name="index">
|
||||
<template #title>
|
||||
<span class="text-[#333] text-[14px]"> v{{ item.version_no }} </span>
|
||||
</template>
|
||||
<div class="px-[20px] py-[20px] bg-overlay timeline-log-wrap whitespace-pre-wrap rounded-[4px]" style="background: rgba(25, 103, 249, 0.03);" v-if="item['upgrade_log']">
|
||||
<div v-html="item['upgrade_log']"></div>
|
||||
</div>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
</el-timeline-item>
|
||||
</el-timeline>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-dialog>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { computed, ref, defineProps, nextTick } from "vue"
|
||||
import { t } from "@/lang"
|
||||
import { getAppVersionList, getFrameworkVersionList } from "@/app/api/module"
|
||||
|
||||
const props = defineProps({
|
||||
upgradeKey: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
})
|
||||
|
||||
const frameworkVersionList = ref([])
|
||||
|
||||
const newVersion: any = computed(() => {
|
||||
return frameworkVersionList.value.length ? frameworkVersionList.value[0] : null
|
||||
})
|
||||
|
||||
const getAppVersionListFn = () => {
|
||||
getAppVersionList({ app_key: props.upgradeKey }).then(({ data }) => {
|
||||
loading.value = false
|
||||
data.forEach((item: any, index) => {
|
||||
if (index == 0) {
|
||||
item.important = 1
|
||||
} else {
|
||||
item.important = 0
|
||||
}
|
||||
})
|
||||
|
||||
frameworkVersionList.value = data
|
||||
})
|
||||
}
|
||||
const getFrameworkVersionListFn = () => {
|
||||
getFrameworkVersionList().then(({ data }) => {
|
||||
loading.value = false
|
||||
data.forEach((item: any, index) => {
|
||||
if (index == 0) {
|
||||
item.important = 1
|
||||
} else {
|
||||
item.important = 0
|
||||
}
|
||||
})
|
||||
frameworkVersionList.value = data
|
||||
})
|
||||
}
|
||||
|
||||
const activeName = ref(0)
|
||||
|
||||
// 提交信息
|
||||
const loading = ref(true)
|
||||
const dialogVisible = ref(false)
|
||||
const open = async () => {
|
||||
nextTick(() => {
|
||||
|
||||
if (props.upgradeKey) {
|
||||
getAppVersionListFn()
|
||||
} else {
|
||||
getFrameworkVersionListFn()
|
||||
}
|
||||
dialogVisible.value = true
|
||||
})
|
||||
|
||||
}
|
||||
const timeSplit = (str: string) => {
|
||||
const [date, time] = str.split(" ")
|
||||
const [hours, minutes] = time.split(":")
|
||||
return [date, `${ hours }:${ minutes }`]
|
||||
}
|
||||
defineExpose({
|
||||
open
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped></style>
|
||||
<style scoped>
|
||||
.el-timeline-item {
|
||||
min-height: 75px;
|
||||
}
|
||||
|
||||
.el-timeline-item >>> .el-timeline-item__node--normal {
|
||||
left: 117px;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
|
||||
background: rgba(25, 103, 249, 0.12) !important;
|
||||
border-radius: 50%;
|
||||
/* 创建圆形 */
|
||||
position: relative;
|
||||
/* 用于定位伪元素 */
|
||||
}
|
||||
|
||||
.el-timeline-item >>> .el-timeline-item__node--normal::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 8px;
|
||||
/* 中心圆直径 */
|
||||
height: 8px;
|
||||
background-color: var(--el-color-primary);
|
||||
/* 中心圆颜色 */
|
||||
border-radius: 50%;
|
||||
/* 中心圆为圆形 */
|
||||
transform: translate(-50%, -50%);
|
||||
/* 居中显示 */
|
||||
}
|
||||
|
||||
.el-timeline-item >>> .el-timeline-item__tail {
|
||||
left: 125px;
|
||||
border-left-color: #dddddd;
|
||||
border-left-style: dashed;
|
||||
margin: 12px 0;
|
||||
margin-top: 24px;
|
||||
height: calc(100% - 24px - 12px);
|
||||
}
|
||||
|
||||
.time-dialog >>> .el-dialog__header {
|
||||
padding: 10px 20px;
|
||||
height: 25px;
|
||||
line-height: 25px;
|
||||
text-align: left;
|
||||
background: #fff;
|
||||
border-bottom: solid 1px #e4e7ed;
|
||||
}
|
||||
|
||||
.time-dialog >>> .el-card__body {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.time-dialog >>> .el-card.is-always-shadow {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.time-dialog >>> .el-dialog__headerbtn .el-dialog__close {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.time-dialog >>> .el-dialog__headerbtn:hover .el-dialog__close {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.time-dialog >>> .el-dialog__headerbtn {
|
||||
top: 14px;
|
||||
}
|
||||
|
||||
.time-dialog >>> .el-collapse {
|
||||
margin-left: 119px;
|
||||
border: none;
|
||||
margin-top: -22px;
|
||||
}
|
||||
|
||||
.time-dialog >>> .el-collapse-item__header {
|
||||
border: none;
|
||||
line-height: 25px;
|
||||
height: 25px;
|
||||
position: relative;
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
.time-dialog >>> .el-collapse-item__wrap {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.time-dialog >>> .el-collapse-item__content {
|
||||
margin-top: 15px;
|
||||
padding-bottom: 0px !important;
|
||||
}
|
||||
|
||||
.time-dialog >>> .el-timeline-item__node--01 {
|
||||
width: 18px !important;
|
||||
height: 18px !important;
|
||||
left: 117px !important;
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
.time-dialog .el-dialog {
|
||||
margin: 0 auto !important;
|
||||
max-height: 90%;
|
||||
overflow: hidden;
|
||||
top: 5%;
|
||||
}
|
||||
|
||||
.time-dialog .el-dialog {
|
||||
margin: 0 auto !important;
|
||||
height: 65%;
|
||||
overflow: hidden;
|
||||
top: 10%;
|
||||
}
|
||||
|
||||
.time-dialog .el-dialog__body {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 46px;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
z-index: 1;
|
||||
overflow: hidden;
|
||||
overflow-y: auto;
|
||||
padding: 10px 20px 0 0;
|
||||
}
|
||||
|
||||
.time-dialog .el-timeline-item__wrapper {
|
||||
top: -20px !important;
|
||||
}
|
||||
.el-scrollbar__bar{
|
||||
z-index:999;
|
||||
}
|
||||
</style>
|
||||
@ -1,140 +1,252 @@
|
||||
<template>
|
||||
<el-dialog v-model="showDialog" :title="t('upgrade.title')" width="850px" :close-on-click-modal="false" :close-on-press-escape="false" :before-close="dialogClose">
|
||||
|
||||
<div v-show="active == 'content'">
|
||||
|
||||
<div class="h-[60vh] flex flex-col" v-if="upgradeContent">
|
||||
<template v-if="upgradeContent">
|
||||
<!-- 检测服务是否到期 -->
|
||||
<template v-if="step == 1 && upgradeContent.upgrade_version != upgradeContent.last_version">
|
||||
<div class="text-lg">
|
||||
本次升级将从<span class="font-bold">{{ upgradeContent.version }}</span>升级到<span class="font-bold">{{ upgradeContent.upgrade_version }}</span>版本
|
||||
<template v-if="upgradeContent.upgrade_version">
|
||||
<span>本次升级将从</span>
|
||||
<span class="font-bold px-[2px]">{{ upgradeContent.version }}</span>
|
||||
<span>升级到</span>
|
||||
<span class="font-bold px-[2px]">{{ upgradeContent.upgrade_version }}</span>
|
||||
<span>版本</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span>当前版本</span>
|
||||
<span class="font-bold px-[2px]">{{ upgradeContent.version }}</span>
|
||||
</template>
|
||||
</div>
|
||||
<div class="mt-[10px]" v-if="upgradeContent.upgrade_version != upgradeContent.last_version">
|
||||
<el-alert type="info" show-icon>
|
||||
<div class="mt-[10px]">
|
||||
<el-alert type="info" show-icon :closable="false">
|
||||
<template #title>
|
||||
当前最新版本为{{ upgradeContent.last_version }},您的服务{{ upgradeContent.expire_time ? `已于${upgradeContent.expire_time}到期` : '长期有效' }}。如需升级到最新版可在<a class="text-primary" href="https://www.niucloud.com" target="_blank">niucloud-admin官网</a>购买相关服务后再进行升级
|
||||
<span>当前最新版本为{{ upgradeContent.last_version }},您的服务{{ upgradeContent.expire_time ? `已于${upgradeContent.expire_time}到期` : '长期有效' }}。</span>
|
||||
<span>如需升级到最新版可在<a class="text-primary" href="https://www.niucloud.com" target="_blank">niucloud-admin官网</a>购买相关服务后再进行升级</span>
|
||||
</template>
|
||||
</el-alert>
|
||||
</div>
|
||||
<el-scrollbar class="flex-1 h-0 mt-[20px]">
|
||||
<div class="mt-[20px]" v-for="(item, index) in upgradeContent.version_list" :key="index">
|
||||
<div class="font-bold text-lg">{{ item.version_no }}</div>
|
||||
<div class="mt-[5px]" v-if="item.release_time">{{ item.release_time }}</div>
|
||||
<div class="mt-[10px] p-[10px] rounded bg-[#f4f4f5] whitespace-pre-wrap !break-all" v-if="item.upgrade_log" v-html="item.upgrade_log"></div>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
<div class="flex justify-end" v-if="upgradeContent.version_list.length">
|
||||
<el-button type="primary" @click="handleUpgrade" :loading="uploading">{{ t('upgrade.upgradeButton') }}</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div v-if="step == 2">
|
||||
<el-steps :active="numberOfSteps" align-center class="number-of-steps" finish-status="success" process-status="process">
|
||||
<el-step :title="t('testDirectoryPermissions')" />
|
||||
<el-step :title="t('backupFiles')" />
|
||||
<el-step :title="t('startUpgrade')" />
|
||||
<el-step :title="t('upgradeEnd')" />
|
||||
</el-steps>
|
||||
<div class="h-[400px]" style="overflow: auto">
|
||||
<!-- <div class="time-dialog-wrap mt-[30px]" v-show="active == 'content'">-->
|
||||
<!-- <el-timeline style="width: 100%">-->
|
||||
<!-- <el-timeline-item v-for="(item, index) in upgradeContent.version_list" :key="index" placement="left">-->
|
||||
<!-- <div class="relative">-->
|
||||
<!-- <span class="text-[#333333] text-[16px] absolute">{{ timeSplit(item.release_time)[0] }}</span>-->
|
||||
<!-- <br />-->
|
||||
<!-- <span class="text-[#999999] text-[14px] w-[78px] block mt-[10px] absolute" style="text-align: right"> {{ timeSplit(item.release_time)[1] }}</span>-->
|
||||
<!-- </div>-->
|
||||
<!-- <el-collapse v-model="activeName" accordion>-->
|
||||
<!-- <el-collapse-item :name="index">-->
|
||||
<!-- <template #title>-->
|
||||
<!-- <span class="text-[#333] text-[16px]"> v{{ item.version_no }} </span>-->
|
||||
<!-- </template>-->
|
||||
|
||||
<div v-show="active == 'upgrade'">
|
||||
<div class="h-[60vh] flex flex-col" v-if="upgradeCheck && !upgradeTask">
|
||||
<el-scrollbar>
|
||||
<div class="bg-[#fff] my-3" v-if="upgradeCheck.dir">
|
||||
<p class="pt-[20px] pl-[20px] ">{{ t('upgrade.dirPermission') }}</p>
|
||||
<div class="px-[20px] pt-[10px] text-[14px] el-table">
|
||||
<el-row class="py-[10px] items table-head-bg pl-[15px] mb-[10px]">
|
||||
<el-col :span="12">
|
||||
<span>{{ t('upgrade.path') }}</span>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<span>{{ t('upgrade.demand') }}</span>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<span>{{ t('status') }}</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="pb-[10px] items pl-[15px]" v-for="item in upgradeCheck.dir.is_readable">
|
||||
<el-col :span="12">
|
||||
<span>{{ item.dir }}</span>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<span>{{ t('upgrade.readable') }}</span>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<span v-if="item.status"><el-icon color="green"><Select /></el-icon></span>
|
||||
<span v-else>
|
||||
<el-icon color="red">
|
||||
<CloseBold />
|
||||
</el-icon>
|
||||
</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="pb-[10px] items pl-[15px]" v-for="item in upgradeCheck.dir.is_write">
|
||||
<el-col :span="12">
|
||||
<span>{{ item.dir }}</span>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<span>{{ t('upgrade.write') }}</span>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<span v-if="item.status"><el-icon color="green"><Select /></el-icon></span>
|
||||
<span v-else>
|
||||
<el-icon color="red">
|
||||
<CloseBold />
|
||||
</el-icon>
|
||||
</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<!-- <div class="px-[20px] py-[20px] bg-overlay timeline-log-wrap whitespace-pre-wrap rounded-[4px]" style="background: rgba(25, 103, 249, 0.03);" v-if="item['upgrade_log']">-->
|
||||
<!-- <div v-html="item['upgrade_log']"></div>-->
|
||||
<!-- </div>-->
|
||||
<!-- </el-collapse-item>-->
|
||||
<!-- </el-collapse>-->
|
||||
<!-- </el-timeline-item>-->
|
||||
<!-- </el-timeline>-->
|
||||
<!-- </div>-->
|
||||
|
||||
<!-- 判断文件权限 -->
|
||||
<div v-show="active == 'upgrade'">
|
||||
<div class="flex flex-col" v-if="upgradeCheck && !upgradeTask">
|
||||
<el-scrollbar>
|
||||
<div class="bg-[#fff] my-3" v-if="upgradeCheck.dir">
|
||||
<div class="px-[20px] pt-[10px] text-[14px] el-table">
|
||||
<el-row class="py-[10px] items table-head-bg pl-[15px] mb-[10px]">
|
||||
<el-col :span="12">
|
||||
<span>{{ t("upgrade.path") }}</span>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<span>{{ t("upgrade.demand") }}</span>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<span>{{ t("status") }}</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<div style="height: calc(300px); overflow: auto">
|
||||
<el-row class="pb-[10px] items pl-[15px]" v-for="item in upgradeCheck.dir.is_readable">
|
||||
<el-col :span="12">
|
||||
<span>{{ item.dir }}</span>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<span>{{ t("upgrade.readable") }}</span>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<span v-if="item.status">
|
||||
<el-icon color="green">
|
||||
<Select />
|
||||
</el-icon>
|
||||
</span>
|
||||
<span v-else>
|
||||
<el-icon color="red">
|
||||
<CloseBold />
|
||||
</el-icon>
|
||||
</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="pb-[10px] items pl-[15px]" v-for="item in upgradeCheck.dir.is_write">
|
||||
<el-col :span="12">
|
||||
<span>{{ item.dir }}</span>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<span>{{ t("upgrade.write") }}</span>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<span v-if="item.status">
|
||||
<el-icon color="green">
|
||||
<Select />
|
||||
</el-icon>
|
||||
</span>
|
||||
<span v-else>
|
||||
<el-icon color="red">
|
||||
<CloseBold />
|
||||
</el-icon>
|
||||
</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
<div class="h-[370px] mt-[30px]" v-show="upgradeTask">
|
||||
<terminal ref="terminalRef" :context="upgradeTask ? upgradeTask.upgrade.app_key : ''" :init-log="null" :show-header="false" :show-log-time="true" @exec-cmd="onExecCmd" />
|
||||
</div>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
<div class="h-[60vh]" v-show="upgradeTask">
|
||||
<terminal ref="terminalRef" :context="upgradeTask ? upgradeTask.upgrade.app_key : ''" :init-log="null" :show-header="false" :show-log-time="true" @exec-cmd="onExecCmd"/>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 是否备份选择 -->
|
||||
<div class="flex flex-col" v-show="active == 'backup'">
|
||||
<el-scrollbar>
|
||||
<div class="bg-[#fff] my-3">
|
||||
|
||||
<div v-show="active == 'complete'">
|
||||
<div class="h-[60vh] flex flex-col">
|
||||
<div class="flex-1 h-0">
|
||||
<el-result icon="success" :title="t('upgrade.upgradeSuccess')"></el-result>
|
||||
<el-alert :title="t('upgrade.upgradeCompleteTips')" type="error" :closable="false" />
|
||||
</div>
|
||||
<div class="flex justify-end">
|
||||
<el-button type="default" @click="showDialog = false">{{ t('upgrade.localBuild') }}</el-button>
|
||||
<el-button type="primary" @click="handleCloudBuild">{{ t('upgrade.cloudBuild') }}</el-button>
|
||||
<div class="px-[20px] pt-[10px] text-[14px] el-table">
|
||||
<el-row class="py-[10px] items table-head-bg pl-[15px] mb-[10px]">
|
||||
<el-col :span="20">
|
||||
<span>功能操作</span>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<span>状态</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="pb-[10px] items pl-[15px]" v-for="item in excludeSteps">
|
||||
<el-col :span="20">
|
||||
<span>{{ item.name }}</span>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<span>
|
||||
<el-icon color="green">
|
||||
<Select />
|
||||
</el-icon>
|
||||
</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
<div class="mt-[50px]" v-show="active == 'complete'">
|
||||
<el-result icon="success" :title="t('upgrade.upgradeSuccess')"></el-result>
|
||||
<el-alert :title="t('upgrade.upgradeCompleteTips')" type="error" :closable="false" v-show="upgradeTask && upgradeTask.executed && !upgradeTask.executed.includes('cloudBuild')"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<!-- 查看升级内容 -->
|
||||
<el-button v-if="step == 1 && upgradeContent.version_list.length" @click="step = 2" type="primary">{{ t("upgrade.upgradeButton") }}</el-button>
|
||||
|
||||
<template v-if="step == 2">
|
||||
<!-- <el-button v-if="active == 'content'" @click="showDialog = false">{{ t("return") }}</el-button>-->
|
||||
<el-button type="primary" :disabled="!is_pass" v-if="active == 'upgrade' && !upgradeTask" @click="() => { active = 'backup'; numberOfSteps = 1 }">{{ t("nextStep") }}</el-button>
|
||||
<el-button v-if="active == 'backup'" @click="() => { active = 'upgrade'; numberOfSteps = 1 } ">{{ t("prev") }}</el-button>
|
||||
<el-button type="primary" v-if="active == 'backup'" :loading="uploading" @click="() => { upgradeAddonFn() }">{{ t("nextStep") }}</el-button>
|
||||
<el-button v-if="active == 'complete'" @click="showDialog = false">{{ t("complete") }}</el-button>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog v-model="upgradeTipsShowDialog" :title="t('warning')" width="500px" draggable>
|
||||
<span v-html="t('upgrade.upgradeTips')"></span>
|
||||
<template #footer>
|
||||
<div class="flex justify-end">
|
||||
<el-button @click="upgradeTipsConfirm(true)" type="primary">{{ t('upgrade.knownToKnow') }}</el-button>
|
||||
<el-button @click="upgradeTipsConfirm()" type="primary" plain>{{ t('upgrade.upgradeButton') }}</el-button>
|
||||
<el-button @click="upgradeTipsShowDialog = false">{{ t('cancel') }}</el-button>
|
||||
<el-button @click="upgradeTipsConfirm(true)" type="primary">{{ t("upgrade.knownToKnow") }}</el-button>
|
||||
<el-button @click="handleUpgrade()" type="primary" plain>{{ t("upgrade.upgradeButton") }}</el-button>
|
||||
<el-button @click="upgradeTipsShowDialog = false">{{ t("cancel") }}</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog v-model="cloudBuildErrorTipsShowDialog" :title="t('warning')" width="500px" draggable :show-close="false">
|
||||
<span v-html="t('upgrade.cloudBuildErrorTips')"></span>
|
||||
<template #footer>
|
||||
<div class="flex justify-end">
|
||||
<el-button @click="cloudBuildError('local')" type="primary">{{ t("upgrade.localBuild") }}</el-button>
|
||||
<el-button @click="cloudBuildError('retry')" type="primary">{{ t("upgrade.cloudBuild") }}({{ retrySecond }}S)</el-button>
|
||||
<el-button @click="cloudBuildError('rollback')" type="primary">{{ t("upgrade.rollback") }}</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, h, watch } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { getVersions } from '@/app/api/auth'
|
||||
import { getFrameworkNewVersion } from '@/app/api/module'
|
||||
import { getUpgradeContent, getUpgradeTask, upgradeAddon, executeUpgrade, preUpgradeCheck, clearUpgradeTask } from '@/app/api/upgrade'
|
||||
import { Terminal, TerminalFlash } from 'vue-web-terminal'
|
||||
import 'vue-web-terminal/lib/theme/dark.css'
|
||||
import { AnyObject } from '@/types/global'
|
||||
import { ElNotification, ElMessage, ElMessageBox } from 'element-plus'
|
||||
import Storage from '@/utils/storage'
|
||||
import { ref, h, watch } from "vue"
|
||||
import { t } from "@/lang"
|
||||
import { getVersions } from "@/app/api/auth"
|
||||
import { getFrameworkNewVersion } from "@/app/api/module"
|
||||
import {
|
||||
getUpgradeContent,
|
||||
getUpgradeTask,
|
||||
upgradeAddon,
|
||||
executeUpgrade,
|
||||
preUpgradeCheck,
|
||||
clearUpgradeTask, upgradeUserOperate
|
||||
} from "@/app/api/upgrade"
|
||||
import { Terminal, TerminalFlash } from "vue-web-terminal"
|
||||
import "vue-web-terminal/lib/theme/dark.css"
|
||||
import { AnyObject } from "@/types/global"
|
||||
import { ElNotification, ElMessage, ElMessageBox } from "element-plus"
|
||||
import Storage from "@/utils/storage"
|
||||
|
||||
const showDialog = ref<boolean>(false)
|
||||
const upgradeContent = ref<null | AnyObject>(null)
|
||||
const upgradeTask = ref<null | AnyObject>(null)
|
||||
const active = ref('content')
|
||||
const active = ref('upgrade')
|
||||
const step = ref(1)
|
||||
const upgradeCheck = ref<null | AnyObject>(null)
|
||||
const uploading = ref(false)
|
||||
const terminalRef: any = ref(null)
|
||||
const emits = defineEmits(['complete', 'cloudbuild'])
|
||||
const emits = defineEmits(["complete", "cloudbuild"])
|
||||
const upgradeTipsShowDialog = ref<boolean>(false)
|
||||
|
||||
let upgradeLog: any = []
|
||||
let errorLog: any = []
|
||||
const cloudBuildErrorTipsShowDialog = ref<boolean>(false)
|
||||
const retrySecond = ref(30)
|
||||
let retrySecondInterval: any = null
|
||||
|
||||
// 升级步骤排除,backupCode 备份代码,backupSql 备份数据库
|
||||
const excludeSteps: any = ref([
|
||||
{
|
||||
name: "备份源码",
|
||||
code: "backupCode"
|
||||
},
|
||||
{
|
||||
name: "备份数据库",
|
||||
code: "backupSql"
|
||||
}
|
||||
])
|
||||
/**
|
||||
* 查询升级任务
|
||||
*/
|
||||
@ -142,66 +254,88 @@ const getUpgradeTaskFn = () => {
|
||||
getUpgradeTask().then(({ data }) => {
|
||||
if (!data) return
|
||||
|
||||
if (!upgradeContent.value) upgradeContent.value = data.upgrade_content
|
||||
|
||||
// 检测有没有正在进行中的升级任务
|
||||
if (!showDialog.value) {
|
||||
showElNotification()
|
||||
return
|
||||
}
|
||||
if (!upgradeTask.value) {
|
||||
terminalRef.value.execute('clear')
|
||||
terminalRef.value.execute('开始升级')
|
||||
terminalRef.value.execute("clear")
|
||||
terminalRef.value.execute("开始升级")
|
||||
}
|
||||
data.log.forEach(item => {
|
||||
|
||||
upgradeTask.value = data
|
||||
|
||||
data.log.forEach((item) => {
|
||||
if (!upgradeLog.includes(item)) {
|
||||
terminalRef.value.pushMessage({content: `正在执行:${item}`})
|
||||
terminalRef.value.pushMessage({ content: `${ item }` })
|
||||
upgradeLog.push(item)
|
||||
}
|
||||
})
|
||||
// 安装失败
|
||||
if (data.error) {
|
||||
data.error.forEach(item => {
|
||||
data.error.forEach((item) => {
|
||||
if (!errorLog.includes(item)) {
|
||||
terminalRef.value.pushMessage({ content: item, class: 'error' })
|
||||
terminalRef.value.pushMessage({ content: item, class: "error" })
|
||||
errorLog.push(item)
|
||||
}
|
||||
})
|
||||
}
|
||||
// 恢复完毕
|
||||
if (data.step == 'restoreComplete') {
|
||||
if (data.step == "restoreComplete") {
|
||||
flashInterval && clearInterval(flashInterval)
|
||||
return
|
||||
}
|
||||
// 升级完成
|
||||
if (data.step == 'upgradeComplete') {
|
||||
active.value = 'complete'
|
||||
if (data.step == "upgradeComplete") {
|
||||
active.value = "complete"
|
||||
numberOfSteps.value = 4
|
||||
notificationEl && notificationEl.close()
|
||||
emits('complete')
|
||||
emits("complete")
|
||||
clearUpgradeTask()
|
||||
return
|
||||
}
|
||||
upgradeTask.value = data
|
||||
numberOfSteps.value = 2
|
||||
active.value = "upgrade"
|
||||
executeUpgradeFn()
|
||||
}).catch()
|
||||
})
|
||||
}
|
||||
|
||||
getUpgradeTaskFn()
|
||||
|
||||
const executeUpgradeFn = () => {
|
||||
executeUpgrade().then(() => {
|
||||
getUpgradeTaskFn()
|
||||
}).catch()
|
||||
}).catch((err) => {
|
||||
if (err.message.indexOf('队列') != -1) {
|
||||
retrySecond.value = 30
|
||||
retrySecondInterval = setInterval(() => {
|
||||
retrySecond.value--
|
||||
if (retrySecond.value == 0) {
|
||||
cloudBuildError('retry')
|
||||
}
|
||||
}, 1000)
|
||||
cloudBuildErrorTipsShowDialog.value = true
|
||||
} else {
|
||||
ElMessage({ message: err.message, type: 'error' })
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
let notificationEl : any = null
|
||||
let notificationEl: any = null
|
||||
/**
|
||||
* 升级中任务提示
|
||||
*/
|
||||
const showElNotification = () => {
|
||||
notificationEl = ElNotification.success({
|
||||
title: t('warning'),
|
||||
title: t("warning"),
|
||||
dangerouslyUseHTMLString: true,
|
||||
message: h('div', {}, [
|
||||
t('upgrade.upgradingTips'),
|
||||
h('span', { class: 'text-primary cursor-pointer', onClick: elNotificationClick }, [t('upgrade.clickView')])
|
||||
]),
|
||||
message: h("div", {}, [t("upgrade.upgradingTips"), h("span", {
|
||||
class: "text-primary cursor-pointer",
|
||||
onClick: elNotificationClick
|
||||
}, [t("upgrade.clickView")])]),
|
||||
duration: 0,
|
||||
showClose: false
|
||||
})
|
||||
@ -209,13 +343,13 @@ const showElNotification = () => {
|
||||
|
||||
const elNotificationClick = () => {
|
||||
showDialog.value = true
|
||||
active.value = 'upgrade'
|
||||
getUpgradeTaskFn()
|
||||
active.value = "upgrade"
|
||||
notificationEl && notificationEl.close()
|
||||
}
|
||||
|
||||
const frameworkVersion = ref('')
|
||||
getVersions().then(res => {
|
||||
const frameworkVersion = ref("")
|
||||
getVersions().then((res) => {
|
||||
frameworkVersion.value = res.data.version.version
|
||||
})
|
||||
const newFrameworkVersion = ref("")
|
||||
@ -226,44 +360,63 @@ getFrameworkNewVersion().then(({ data }) => {
|
||||
/**
|
||||
* 执行升级
|
||||
*/
|
||||
const handleUpgrade = async () => {
|
||||
const is_pass = ref(false)
|
||||
const repeat = ref(false)
|
||||
|
||||
const handleUpgrade = async() => {
|
||||
if (repeat.value) return
|
||||
repeat.value = true
|
||||
const appKey = upgradeContent.value?.app.app_key != "niucloud-admin" ? upgradeContent.value?.app.app_key : ""
|
||||
|
||||
await preUpgradeCheck(appKey).then(async ({ data }) => {
|
||||
upgradeCheck.value = data
|
||||
is_pass.value = data.is_pass
|
||||
active.value = "upgrade"
|
||||
!upgradeTask.value ? (numberOfSteps.value = 0) : numberOfSteps.value
|
||||
upgradeTipsShowDialog.value = false
|
||||
showDialog.value = true
|
||||
repeat.value = false
|
||||
}).catch(() => {
|
||||
repeat.value = true
|
||||
})
|
||||
}
|
||||
|
||||
const upgradeAddonFn = () => {
|
||||
if (!is_pass.value) return
|
||||
if (uploading.value) return
|
||||
uploading.value = true
|
||||
|
||||
const appKey = upgradeContent.value?.app.app_key != 'niucloud-admin' ? upgradeContent.value?.app.app_key : ''
|
||||
const appKey = upgradeContent.value?.app.app_key != "niucloud-admin" ? upgradeContent.value?.app.app_key : ""
|
||||
|
||||
await preUpgradeCheck(appKey).then(async({ data }) => {
|
||||
if (data.is_pass) {
|
||||
await upgradeAddon(appKey).then(() => {
|
||||
getUpgradeTaskFn()
|
||||
}).catch(() => {
|
||||
uploading.value = false
|
||||
})
|
||||
} else {
|
||||
upgradeCheck.value = data
|
||||
}
|
||||
}).catch()
|
||||
|
||||
if (uploading.value) active.value = 'upgrade'
|
||||
upgradeAddon(appKey).then(() => {
|
||||
getUpgradeTaskFn()
|
||||
}).catch(() => {
|
||||
uploading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
const open = (addonKey: string = '') => {
|
||||
const open = (addonKey: string = "", callback = null) => {
|
||||
if (upgradeTask.value) {
|
||||
ElMessage({ message: '已有正在执行中的升级任务', type: 'error' })
|
||||
ElMessage({ message: "已有正在执行中的升级任务", type: "error" })
|
||||
showDialog.value = true
|
||||
if (callback) callback()
|
||||
} else {
|
||||
if (addonKey && frameworkVersion.value != newFrameworkVersion.value) {
|
||||
ElMessage({ message: '存在新版本框架,请先升级框架', type: 'error' })
|
||||
ElMessage({ message: "存在新版本框架,请先升级框架", type: "error" })
|
||||
if (callback) callback()
|
||||
return
|
||||
}
|
||||
getUpgradeContent(addonKey).then(({ data }) => {
|
||||
upgradeContent.value = data
|
||||
if (Storage.get('upgradeTipsLock')) {
|
||||
showDialog.value = true
|
||||
if (Storage.get("upgradeTipsLock")) {
|
||||
handleUpgrade()
|
||||
} else {
|
||||
upgradeTipsShowDialog.value = true
|
||||
}
|
||||
}).catch()
|
||||
if (callback) callback()
|
||||
}).catch(() => {
|
||||
if (callback) callback()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -273,11 +426,11 @@ const open = (addonKey: string = '') => {
|
||||
let flashInterval: any = null
|
||||
const terminalFlash = new TerminalFlash()
|
||||
const onExecCmd = (key, command, success, failed, name) => {
|
||||
if (command == '开始升级') {
|
||||
if (command == "开始升级") {
|
||||
success(terminalFlash)
|
||||
const frames = makeIterator(['/', '——', '\\', '|'])
|
||||
const frames = makeIterator(["/", "——", "\\", "|"])
|
||||
flashInterval = setInterval(() => {
|
||||
terminalFlash.flush('> ' + frames.next().value)
|
||||
terminalFlash.flush("> " + frames.next().value)
|
||||
}, 150)
|
||||
}
|
||||
}
|
||||
@ -286,7 +439,7 @@ const makeIterator = (array: string[]) => {
|
||||
var nextIndex = 0
|
||||
return {
|
||||
next() {
|
||||
if ((nextIndex + 1) == array.length) {
|
||||
if (nextIndex + 1 == array.length) {
|
||||
nextIndex = 0
|
||||
}
|
||||
return { value: array[nextIndex++] }
|
||||
@ -295,53 +448,78 @@ const makeIterator = (array: string[]) => {
|
||||
}
|
||||
|
||||
const dialogClose = (done: () => {}) => {
|
||||
if (active.value == 'upgrade' && upgradeTask.value && !upgradeTask.value.error) {
|
||||
ElMessageBox.confirm(
|
||||
t('upgrade.showDialogCloseTips'),
|
||||
t('warning'),
|
||||
{
|
||||
confirmButtonText: t('confirm'),
|
||||
cancelButtonText: t('cancel'),
|
||||
type: 'warning'
|
||||
}
|
||||
).then(() => {
|
||||
if (active.value == "upgrade" && upgradeTask.value && ['upgradeComplete', 'restoreComplete'].includes(upgradeTask.value.step) === false) {
|
||||
ElMessageBox.confirm(t("upgrade.showDialogCloseTips"), t("warning"), {
|
||||
confirmButtonText: t("confirm"),
|
||||
cancelButtonText: t("cancel"),
|
||||
type: "warning"
|
||||
}).then(() => {
|
||||
done()
|
||||
}).catch(() => { })
|
||||
})
|
||||
} else {
|
||||
done()
|
||||
}
|
||||
}
|
||||
|
||||
watch(() => showDialog.value, () => {
|
||||
if (!showDialog.value) {
|
||||
clearUpgradeTaskFn()
|
||||
watch(
|
||||
() => showDialog.value,
|
||||
() => {
|
||||
if (!showDialog.value) {
|
||||
clearUpgradeTaskFn()
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
const clearUpgradeTaskFn = () => {
|
||||
active.value = 'content'
|
||||
active.value = "upgrade"
|
||||
uploading.value = false
|
||||
upgradeTask.value = null
|
||||
upgradeLog = []
|
||||
errorLog = []
|
||||
numberOfSteps.value = 0
|
||||
flashInterval && clearInterval(flashInterval)
|
||||
clearUpgradeTask().then(() => {}).catch()
|
||||
retrySecondInterval && clearInterval(retrySecondInterval)
|
||||
clearUpgradeTask().then(() => {
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 云编译
|
||||
* 云编译队列不足操作
|
||||
* @param event
|
||||
*/
|
||||
const handleCloudBuild = () => {
|
||||
showDialog.value = false
|
||||
emits('cloudbuild')
|
||||
const cloudBuildError = (event: string) => {
|
||||
cloudBuildErrorTipsShowDialog.value = false
|
||||
switch (event) {
|
||||
case "local":
|
||||
upgradeUserOperate(event).then(() => {
|
||||
getUpgradeTaskFn()
|
||||
})
|
||||
break
|
||||
case "retry":
|
||||
executeUpgradeFn()
|
||||
retrySecondInterval && clearInterval(retrySecondInterval)
|
||||
break
|
||||
case "rollback":
|
||||
upgradeUserOperate(event).then(() => {
|
||||
getUpgradeTaskFn()
|
||||
})
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
const timeSplit = (str: string) => {
|
||||
const [date, time] = str.split(" ")
|
||||
const [hours, minutes] = time.split(":")
|
||||
return [date, `${ hours }:${ minutes }`]
|
||||
}
|
||||
|
||||
const upgradeTipsConfirm = (isLock: boolean = false) => {
|
||||
isLock && Storage.set({ key: 'upgradeTipsLock', data: isLock })
|
||||
isLock && Storage.set({ key: "upgradeTipsLock", data: isLock })
|
||||
upgradeTipsShowDialog.value = false
|
||||
!isLock && (showDialog.value = true)
|
||||
}
|
||||
|
||||
const activeName = ref(0)
|
||||
const numberOfSteps = ref(0)
|
||||
defineExpose({
|
||||
open
|
||||
})
|
||||
@ -351,7 +529,187 @@ defineExpose({
|
||||
.table-head-bg {
|
||||
background-color: var(--el-table-header-bg-color);
|
||||
}
|
||||
|
||||
:deep(.terminal .t-log-box span) {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
::v-deep .number-of-steps {
|
||||
.el-step__line {
|
||||
margin: 0 25px;
|
||||
background: #dddddd;
|
||||
}
|
||||
|
||||
.el-step__head {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.is-success {
|
||||
color: var(--el-color-primary);
|
||||
border-color: var(--el-color-primary);
|
||||
|
||||
.el-step__icon {
|
||||
background: var(--el-color-primary);
|
||||
|
||||
box-shadow: 0 0 0 4px var(--el-color-primary-light-9);
|
||||
|
||||
i {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.el-step__line {
|
||||
margin: 0 25px;
|
||||
background: var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
.is-process {
|
||||
color: var(--el-color-primary);
|
||||
font-weight: inherit;
|
||||
|
||||
// font-size: 18px;
|
||||
.el-step__icon {
|
||||
padding: 10px;
|
||||
border: 1px solid var(--el-color-primary);
|
||||
box-shadow: 0 0 0 4px var(--el-color-primary-light-9);
|
||||
}
|
||||
}
|
||||
|
||||
.is-wait {
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style scoped>
|
||||
.el-timeline-item {
|
||||
min-height: 100px;
|
||||
}
|
||||
|
||||
.el-timeline-item >>> .el-timeline-item__node--normal {
|
||||
left: 117px;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
|
||||
background: rgba(25, 103, 249, 0.12) !important;
|
||||
border-radius: 50%;
|
||||
/* 创建圆形 */
|
||||
position: relative;
|
||||
/* 用于定位伪元素 */
|
||||
}
|
||||
|
||||
.el-timeline-item >>> .el-timeline-item__node--normal::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 8px;
|
||||
/* 中心圆直径 */
|
||||
height: 8px;
|
||||
background-color: var(--el-color-primary);
|
||||
/* 中心圆颜色 */
|
||||
border-radius: 50%;
|
||||
/* 中心圆为圆形 */
|
||||
transform: translate(-50%, -50%);
|
||||
/* 居中显示 */
|
||||
}
|
||||
|
||||
.el-timeline-item >>> .el-timeline-item__tail {
|
||||
left: 125px;
|
||||
border-left-color: #dddddd;
|
||||
border-left-style: dashed;
|
||||
margin: 12px 0;
|
||||
margin-top: 24px;
|
||||
height: calc(100% - 24px - 12px);
|
||||
}
|
||||
|
||||
.time-dialog-wrap >>> .el-dialog__header {
|
||||
padding: 10px 20px;
|
||||
height: 25px;
|
||||
line-height: 25px;
|
||||
text-align: left;
|
||||
background: #fff;
|
||||
border-bottom: solid 1px #e4e7ed;
|
||||
}
|
||||
|
||||
.time-dialog-wrap >>> .el-card__body {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.time-dialog-wrap >>> .el-card.is-always-shadow {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.time-dialog-wrap >>> .el-dialog__headerbtn .el-dialog__close {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.time-dialog-wrap >>> .el-dialog__headerbtn:hover .el-dialog__close {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.time-dialog-wrap >>> .el-dialog__headerbtn {
|
||||
top: 14px;
|
||||
}
|
||||
|
||||
.time-dialog-wrap >>> .el-collapse {
|
||||
margin-left: 119px;
|
||||
border: none;
|
||||
margin-top: -22px;
|
||||
}
|
||||
|
||||
.time-dialog-wrap >>> .el-collapse-item__header {
|
||||
border: none;
|
||||
line-height: 25px;
|
||||
height: 25px;
|
||||
position: relative;
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
.time-dialog-wrap >>> .el-collapse-item__wrap {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.time-dialog-wrap >>> .el-collapse-item__content {
|
||||
margin-top: 15px;
|
||||
padding-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.time-dialog-wrap >>> .el-timeline-item__node--01 {
|
||||
width: 18px !important;
|
||||
height: 18px !important;
|
||||
left: 117px !important;
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
.time-dialog-wrap .el-dialog {
|
||||
margin: 0 auto !important;
|
||||
max-height: 90%;
|
||||
overflow: hidden;
|
||||
top: 5%;
|
||||
}
|
||||
|
||||
.time-dialog-wrap .el-dialog {
|
||||
margin: 0 auto !important;
|
||||
height: 65%;
|
||||
overflow: hidden;
|
||||
top: 10%;
|
||||
}
|
||||
|
||||
.time-dialog-wrap .el-dialog__body {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 46px;
|
||||
bottom: 0px;
|
||||
right: 0;
|
||||
z-index: 1;
|
||||
overflow: hidden;
|
||||
overflow-y: auto;
|
||||
padding: 10px 20px 0 0;
|
||||
}
|
||||
|
||||
.time-dialog-wrap .el-timeline-item__wrapper {
|
||||
top: -20px !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -25,11 +25,9 @@ import { t } from '@/lang'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import { deepClone } from '@/utils/common'
|
||||
import { getUserInfo, setUserInfo } from '@/app/api/personal'
|
||||
import { useRouter } from 'vue-router'
|
||||
import useUserStore from '@/stores/modules/user'
|
||||
|
||||
const userStore = useUserStore()
|
||||
const router = useRouter()
|
||||
// 提交信息
|
||||
const saveInfo: any = reactive({})
|
||||
const formRef = ref<FormInstance>()
|
||||
|
||||
@ -1,19 +1,19 @@
|
||||
{
|
||||
"companyName": "授权主体",
|
||||
"siteAddress": "授权域名",
|
||||
"contactName": "授权联系人",
|
||||
"authCode": "授权码",
|
||||
"authSecret": "授权秘钥",
|
||||
"createTime": "授权时间",
|
||||
"expireTime": "到期时间",
|
||||
"authApp": "授权应用",
|
||||
"authAppKey": "应用标识",
|
||||
"siteAddressTips": "授权域名不匹配",
|
||||
"authCodePlaceholder": "请输入授权码",
|
||||
"authSecretPlaceholder": "请输入授权秘钥",
|
||||
"updateCode": "重新绑定",
|
||||
"notHaveAuth": "还没有授权?去购买",
|
||||
"authInfoTips": "授权码和授权秘钥可在Niucloud官网我的授权 授权详情中查看",
|
||||
"cloudBuildTips": "是否要进行云编译该操作可能会影响到正在访问的客户是否要继续操作?",
|
||||
"versionTips":"已经升级到最新版本"
|
||||
"companyName": "授权主体",
|
||||
"siteAddress": "授权域名",
|
||||
"contactName": "授权联系人",
|
||||
"authCode": "授权码",
|
||||
"authSecret": "授权秘钥",
|
||||
"createTime": "授权时间",
|
||||
"expireTime": "到期时间",
|
||||
"authApp": "授权应用",
|
||||
"authAppKey": "应用标识",
|
||||
"siteAddressTips": "授权域名不匹配",
|
||||
"authCodePlaceholder": "请输入授权码",
|
||||
"authSecretPlaceholder": "请输入授权秘钥",
|
||||
"updateCode": "重新绑定",
|
||||
"notHaveAuth": "还没有授权?去购买",
|
||||
"authInfoTips": "授权码和授权秘钥可在Niucloud官网我的授权 授权详情中查看",
|
||||
"cloudBuildTips": "是否要进行云编译该操作可能会影响到正在访问的客户是否要继续操作?",
|
||||
"versionTips": "已经升级到最新版本"
|
||||
}
|
||||
|
||||
67
admin/src/app/lang/zh-cn/app.shorezj.json
Normal file
@ -0,0 +1,67 @@
|
||||
{
|
||||
"search": "搜索应用名称",
|
||||
"appName": "应用名/版本信息",
|
||||
"introduction": "简介",
|
||||
"type": "类型",
|
||||
"app": "应用",
|
||||
"addon": "插件",
|
||||
"noPlug": "暂无应用",
|
||||
"install": "安装",
|
||||
"unload": "卸载",
|
||||
"installLabel": "已安装",
|
||||
"uninstalledLabel": "未安装",
|
||||
"version": "版本",
|
||||
"title": "名称",
|
||||
"desc": "简介",
|
||||
"plugDetail": "插件信息",
|
||||
"author": "作者",
|
||||
"detail": "详情",
|
||||
"addonInstall": "插件安装",
|
||||
"dirPermission": "目录读写权限",
|
||||
"path": "路径",
|
||||
"demand": "要求",
|
||||
"readable": "可读",
|
||||
"write": "可写",
|
||||
"packageManageTool": "包管理工具",
|
||||
"name": "名称",
|
||||
"addonInstallSuccess": "插件安装成功",
|
||||
"envCheck": "环境检查",
|
||||
"installProgress": "安装进度",
|
||||
"installComplete": "安装完成",
|
||||
"localAppText": "插件管理",
|
||||
"marketAppText": "官方市场",
|
||||
"installShowDialogCloseTips": "安装任务尚未完成,关闭将取消安装任务,是否要继续关闭?",
|
||||
"marketDevelopMessage": "官方市场正在开发中!",
|
||||
"jobError": "任务队列未启动 请在服务端源码部署目录打开终端执行 php think queue:listen",
|
||||
"conflictFiles": "冲突文件",
|
||||
"process": "启动进程",
|
||||
"open": "开启",
|
||||
"down": "下载",
|
||||
"addonVersion": "插件版本",
|
||||
"versionCode": "版本号",
|
||||
"createTime": "发布时间",
|
||||
"buyLabel": "已购买",
|
||||
"installTips": "安装后需手动更新插件引用的依赖和编译各个端口的前端源码",
|
||||
"localInstall": "本地安装",
|
||||
"cloudInstall": "一键云安装",
|
||||
"cloudInstallTips": "云安装可实现一键安装,安装后无需手动更新依赖和编译前端源码",
|
||||
"installingTips": "有插件正在安装中请等待安装完成之后再进行其他操作,点击查看",
|
||||
"installPercent": "安装进度",
|
||||
"downloading": "下载中",
|
||||
"authTips": "云安装需先绑定授权码,如果已有授权请先进行绑定,没有授权可到niucloud官网购买云服务之后再进行操作",
|
||||
"toBind": "绑定授权",
|
||||
"toNiucloud": "去niucloud官网",
|
||||
"descriptionLeft": "暂无任何应用,马上去",
|
||||
"link": "官方应用市场",
|
||||
"descriptionRight": "逛逛",
|
||||
"installed-empty": "暂未安装任何应用,请先安装",
|
||||
"siteAddressTips": "授权域名不匹配",
|
||||
"authCodePlaceholder": "请输入授权码",
|
||||
"authSecretPlaceholder": "请输入授权秘钥",
|
||||
"updateCode": "重新绑定",
|
||||
"notHaveAuth": "还没有授权?去购买",
|
||||
"authInfoTips": "授权码和授权秘钥可在Niucloud官网我的授权 授权详情中查看",
|
||||
"addonUninstall": "插件卸载",
|
||||
"appIdentification": "应用标识",
|
||||
"tipText": "标识指开发应用或插件的文件夹名称"
|
||||
}
|
||||
18
admin/src/app/lang/zh-cn/app.upgrade.json
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"companyName": "授权主体",
|
||||
"siteAddress": "授权域名",
|
||||
"contactName": "授权联系人",
|
||||
"authCode": "授权码",
|
||||
"authSecret": "授权秘钥",
|
||||
"createTime": "授权时间",
|
||||
"expireTime": "到期时间",
|
||||
"authApp": "授权应用",
|
||||
"authAppKey": "应用标识",
|
||||
"siteAddressTips": "授权域名不匹配",
|
||||
"authCodePlaceholder": "请输入授权码",
|
||||
"authSecretPlaceholder": "请输入授权秘钥",
|
||||
"updateCode": "重新绑定",
|
||||
"notHaveAuth": "还没有授权?去购买",
|
||||
"authInfoTips": "授权码和授权秘钥可在Niucloud官网我的授权 授权详情中查看",
|
||||
"versionTips": "已经升级到最新版本"
|
||||
}
|
||||
@ -50,7 +50,7 @@
|
||||
"cashOutInfo":"收款方信息",
|
||||
"transferCode":"收款码",
|
||||
"realname":"真实姓名",
|
||||
"account":"账号",
|
||||
"account":"收款账号",
|
||||
"bankRealname":"持卡人姓名",
|
||||
"remark":"备注",
|
||||
"remarkPlaceholder":"请输入备注",
|
||||
|
||||
@ -1,76 +1,78 @@
|
||||
{
|
||||
"search":"搜索应用名称",
|
||||
"appName":"应用名/版本信息",
|
||||
"introduction":"简介",
|
||||
"type":"类型",
|
||||
"app":"应用",
|
||||
"addon":"插件",
|
||||
"noPlug":"暂无应用",
|
||||
"install":"安装",
|
||||
"unload":"卸载",
|
||||
"installLabel":"已安装",
|
||||
"uninstalledLabel":"未安装",
|
||||
"version":"版本",
|
||||
"title":"名称",
|
||||
"desc":"简介",
|
||||
"plugDetail": "插件信息",
|
||||
"author": "作者",
|
||||
"detail":"详情",
|
||||
"addonInstall": "插件安装",
|
||||
"dirPermission": "目录读写权限",
|
||||
"path": "路径",
|
||||
"demand": "要求",
|
||||
"readable": "可读",
|
||||
"write": "可写",
|
||||
"packageManageTool": "包管理工具",
|
||||
"name": "名称",
|
||||
"addonInstallSuccess": "插件安装成功",
|
||||
"envCheck": "环境检查",
|
||||
"installProgress": "安装进度",
|
||||
"installComplete": "安装完成",
|
||||
"localAppText":"插件管理",
|
||||
"marketAppText":"官方市场",
|
||||
"installShowDialogCloseTips": "安装任务尚未完成,关闭将取消安装任务,是否要继续关闭?",
|
||||
"marketDevelopMessage":"官方市场正在开发中!",
|
||||
"jobError": "任务队列未启动 请在服务端源码部署目录打开终端执行 php think queue:listen",
|
||||
"conflictFiles": "冲突文件",
|
||||
"process": "启动进程",
|
||||
"open": "开启",
|
||||
"down": "下载",
|
||||
"installDown":"未安装(重新下载)",
|
||||
"unloadDown":"已安装(重新下载)",
|
||||
"addonVersion": "插件版本",
|
||||
"versionCode": "版本号",
|
||||
"createTime": "发布时间",
|
||||
"buyLabel": "已购买",
|
||||
"installTips": "安装后需手动更新插件引用的依赖和编译各个端口的前端源码",
|
||||
"localInstall":"本地安装",
|
||||
"cloudInstall": "一键云安装",
|
||||
"cloudInstallTips": "云安装可实现一键安装,安装后无需手动更新依赖和编译前端源码",
|
||||
"installingTips": "有插件正在安装中请等待安装完成之后再进行其他操作,点击查看",
|
||||
"installPercent": "安装进度",
|
||||
"downloading": "下载中",
|
||||
"authTips": "云安装需先绑定授权码,如果已有授权请先进行绑定,没有授权可到niucloud官网购买云服务之后再进行操作",
|
||||
"toBind": "绑定授权",
|
||||
"toNiucloud": "去niucloud官网",
|
||||
"descriptionLeft": "暂无任何应用,马上去",
|
||||
"buyDescriptionLeft": "您还没有购买过应用,马上去",
|
||||
"link": "官方应用市场",
|
||||
"descriptionRight": "逛逛",
|
||||
"installed-empty": "暂未安装任何应用",
|
||||
"siteAddressTips": "授权域名不匹配",
|
||||
"authCodePlaceholder": "请输入授权码",
|
||||
"authSecretPlaceholder": "请输入授权秘钥",
|
||||
"updateCode": "重新绑定",
|
||||
"notHaveAuth": "还没有授权?去购买",
|
||||
"authInfoTips": "授权码和授权秘钥可在Niucloud官网我的授权 授权详情中查看",
|
||||
"addonUninstall": "插件卸载",
|
||||
"appIdentification":"应用标识",
|
||||
"tipText":"标识指开发应用或插件的文件夹名称",
|
||||
"uninstallTips": "是否要卸载该插件?",
|
||||
"upgrade": "升级",
|
||||
"newVersion": "最新版本",
|
||||
"cloudBuild": "云编译",
|
||||
"cloudBuildTips": "是否要进行云编译该操作可能会影响到正在访问的客户是否要继续操作?",
|
||||
"deleteAddonTips": "删除插件会把插件目录连同文件全部删除,确定要删除吗?"
|
||||
"search": "搜索应用名称",
|
||||
"appName": "应用名/版本信息",
|
||||
"introduction": "简介",
|
||||
"type": "类型",
|
||||
"app": "应用",
|
||||
"addon": "插件",
|
||||
"noPlug": "暂无应用",
|
||||
"install": "安装",
|
||||
"unload": "卸载",
|
||||
"installLabel": "已安装",
|
||||
"uninstalledLabel": "未安装",
|
||||
"version": "版本",
|
||||
"title": "名称",
|
||||
"desc": "简介",
|
||||
"plugDetail": "插件信息",
|
||||
"author": "作者",
|
||||
"detail": "详情",
|
||||
"addonInstall": "插件安装",
|
||||
"dirPermission": "目录读写权限",
|
||||
"path": "路径",
|
||||
"demand": "要求",
|
||||
"readable": "可读",
|
||||
"write": "可写",
|
||||
"packageManageTool": "包管理工具",
|
||||
"name": "名称",
|
||||
"addonInstallSuccess": "插件安装成功",
|
||||
"envCheck": "环境检查",
|
||||
"installProgress": "安装进度",
|
||||
"installComplete": "安装完成",
|
||||
"localAppText": "插件管理",
|
||||
"marketAppText": "官方市场",
|
||||
"installShowDialogCloseTips": "安装任务尚未完成,关闭将取消安装任务,是否要继续关闭?",
|
||||
"marketDevelopMessage": "官方市场正在开发中!",
|
||||
"jobError": "任务队列未启动 请在服务端源码部署目录打开终端执行 php think queue:listen",
|
||||
"conflictFiles": "冲突文件",
|
||||
"process": "启动进程",
|
||||
"open": "开启",
|
||||
"down": "下载",
|
||||
"installDown": "未安装(重新下载)",
|
||||
"unloadDown": "已安装(重新下载)",
|
||||
"addonVersion": "插件版本",
|
||||
"versionCode": "版本号",
|
||||
"createTime": "发布时间",
|
||||
"buyLabel": "已购买",
|
||||
"recentlyUpdated": "最近更新",
|
||||
"installTips": "安装后需手动更新插件引用的依赖和编译各个端口的前端源码",
|
||||
"localInstall": "本地安装",
|
||||
"cloudInstall": "一键云安装",
|
||||
"cloudInstallTips": "云安装可实现一键安装,安装后无需手动更新依赖和编译前端源码",
|
||||
"installingTips": "有插件正在安装中请等待安装完成之后再进行其他操作,点击查看",
|
||||
"installPercent": "安装进度",
|
||||
"downloading": "下载中",
|
||||
"authTips": "云安装需先绑定授权码,如果已有授权请先进行绑定,没有授权可到niucloud官网购买云服务之后再进行操作",
|
||||
"toBind": "绑定授权",
|
||||
"toNiucloud": "去niucloud官网",
|
||||
"descriptionLeft": "暂无任何应用,马上去",
|
||||
"buyDescriptionLeft": "您还没有购买过应用,马上去",
|
||||
"link": "官方应用市场",
|
||||
"descriptionRight": "逛逛",
|
||||
"installed-empty": "暂未安装任何应用",
|
||||
"recentlyUpdatedEmpty": "暂无最近更新应用",
|
||||
"siteAddressTips": "授权域名不匹配",
|
||||
"authCodePlaceholder": "请输入授权码",
|
||||
"authSecretPlaceholder": "请输入授权秘钥",
|
||||
"updateCode": "重新绑定",
|
||||
"notHaveAuth": "还没有授权?去购买",
|
||||
"authInfoTips": "授权码和授权秘钥可在Niucloud官网我的授权 授权详情中查看",
|
||||
"addonUninstall": "插件卸载",
|
||||
"appIdentification": "应用标识",
|
||||
"tipText": "标识指开发应用或插件的文件夹名称",
|
||||
"uninstallTips": "是否要卸载该插件?",
|
||||
"upgrade": "一键升级",
|
||||
"newVersion": "最新版本",
|
||||
"cloudBuild": "云编译",
|
||||
"cloudBuildTips": "是否要进行云编译该操作可能会影响到正在访问的客户是否要继续操作?",
|
||||
"deleteAddonTips": "删除插件会把插件目录连同文件全部删除,确定要删除吗?"
|
||||
}
|
||||
|
||||
@ -29,6 +29,7 @@
|
||||
"continueSign": "连签天数",
|
||||
"continueSignFormatError": "连签天数格式错误",
|
||||
"continueSignBerweenDays": "连签天数为2-365天",
|
||||
"continueSignMustLessThanSignPeriod": "连签天数不能大于签到周期",
|
||||
"receiveLimit": "领取限制",
|
||||
"noLimit": "不限制",
|
||||
"everyOneLimit": "每人限领",
|
||||
|
||||
@ -1,31 +1,31 @@
|
||||
{
|
||||
"hotelVerify": "订单核销",
|
||||
"verifyRecord": "核销记录",
|
||||
"verifyTime": "核销时间",
|
||||
"orderNo": "订单编号",
|
||||
"orderNoPlaceholder": "请输入订单编号",
|
||||
"OrderInfo": "订单信息",
|
||||
"buyerInfo": "购买人信息",
|
||||
"verifyCode": "核销码",
|
||||
"verifyCodePlaceholder": "请输入核销码",
|
||||
"verifyer": "核销人",
|
||||
"startDate": "开始时间",
|
||||
"endDate": "结束时间",
|
||||
"mobile": "联系方式",
|
||||
"searchValueEmptyTips": "请输入搜索内容",
|
||||
"verify": "核销",
|
||||
"buyInfo": "预订信息",
|
||||
"orderRefunding": "该订单正在维权中不能进行核销",
|
||||
"verifyTips": "是否要核销该订单?",
|
||||
"toOrder": "查看订单",
|
||||
"verifyType": "核销类型",
|
||||
"verifyTypePlaceholder": "请选择核销类型",
|
||||
"verifier": "核销员",
|
||||
"createTime":"添加时间",
|
||||
"addVerifier":"添加核销员",
|
||||
"verifierDeleteTips":"确定要删除该核销员吗?",
|
||||
"memberInfo": "会员信息",
|
||||
"memberIdPlaceholder": "请选择会员",
|
||||
"member": "会员",
|
||||
"searchPlaceholder": "请输入会员昵称搜索"
|
||||
"hotelVerify": "订单核销",
|
||||
"verifyRecord": "核销记录",
|
||||
"verifyTime": "核销时间",
|
||||
"orderNo": "订单编号",
|
||||
"orderNoPlaceholder": "请输入订单编号",
|
||||
"OrderInfo": "订单信息",
|
||||
"buyerInfo": "购买人信息",
|
||||
"verifyCode": "核销码",
|
||||
"verifyCodePlaceholder": "请输入核销码",
|
||||
"verifyer": "核销人",
|
||||
"startDate": "开始时间",
|
||||
"endDate": "结束时间",
|
||||
"mobile": "联系方式",
|
||||
"searchValueEmptyTips": "请输入搜索内容",
|
||||
"verify": "核销",
|
||||
"buyInfo": "预订信息",
|
||||
"orderRefunding": "该订单正在维权中不能进行核销",
|
||||
"verifyTips": "是否要核销该订单?",
|
||||
"toOrder": "查看订单",
|
||||
"verifyType": "核销类型",
|
||||
"verifyTypePlaceholder": "请选择核销类型",
|
||||
"verifier": "核销员",
|
||||
"createTime": "添加时间",
|
||||
"addVerifier": "添加核销员",
|
||||
"verifierDeleteTips": "确定要删除该核销员吗?",
|
||||
"memberInfo": "会员信息",
|
||||
"memberIdPlaceholder": "请选择会员",
|
||||
"member": "会员",
|
||||
"searchPlaceholder": "请输入会员编号/昵称/手机号"
|
||||
}
|
||||
@ -1,32 +1,32 @@
|
||||
{
|
||||
"hotelVerify": "订单核销",
|
||||
"verifyRecord": "核销记录",
|
||||
"verifyTime": "核销时间",
|
||||
"orderNo": "订单编号",
|
||||
"orderNoPlaceholder": "请输入订单编号",
|
||||
"verifyInfo": "核销信息",
|
||||
"buyerInfo": "购买人信息",
|
||||
"verifyCode": "核销码",
|
||||
"verifyCodePlaceholder": "请输入核销码",
|
||||
"verifyer": "核销人",
|
||||
"startDate": "开始时间",
|
||||
"endDate": "结束时间",
|
||||
"mobile": "联系方式",
|
||||
"searchValueEmptyTips": "请输入搜索内容",
|
||||
"verify": "核销",
|
||||
"buyInfo": "预订信息",
|
||||
"orderRefunding": "该订单正在维权中不能进行核销",
|
||||
"verifyTips": "是否要核销该订单?",
|
||||
"toOrder": "查看订单",
|
||||
"verifyType": "核销类型",
|
||||
"verifyTypePlaceholder": "请选择核销类型",
|
||||
"verifier": "核销员",
|
||||
"verifierPlaceholder": "请选择核销员",
|
||||
"createTime":"添加时间",
|
||||
"addVerifier":"添加核销员",
|
||||
"verifierDeleteTips":"确定要删除该核销员吗?",
|
||||
"memberInfo": "会员信息",
|
||||
"memberIdPlaceholder": "请选择会员",
|
||||
"member": "会员",
|
||||
"searchPlaceholder": "请输入会员昵称搜索"
|
||||
"hotelVerify": "订单核销",
|
||||
"verifyRecord": "核销记录",
|
||||
"verifyTime": "核销时间",
|
||||
"orderNo": "订单编号",
|
||||
"orderNoPlaceholder": "请输入订单编号",
|
||||
"verifyInfo": "核销信息",
|
||||
"buyerInfo": "购买人信息",
|
||||
"verifyCode": "核销码",
|
||||
"verifyCodePlaceholder": "请输入核销码",
|
||||
"verifyer": "核销人",
|
||||
"startDate": "开始时间",
|
||||
"endDate": "结束时间",
|
||||
"mobile": "联系方式",
|
||||
"searchValueEmptyTips": "请输入搜索内容",
|
||||
"verify": "核销",
|
||||
"buyInfo": "预订信息",
|
||||
"orderRefunding": "该订单正在维权中不能进行核销",
|
||||
"verifyTips": "是否要核销该订单?",
|
||||
"toOrder": "查看订单",
|
||||
"verifyType": "核销类型",
|
||||
"verifyTypePlaceholder": "请选择核销类型",
|
||||
"verifier": "核销员",
|
||||
"verifierPlaceholder": "请选择核销员",
|
||||
"createTime": "添加时间",
|
||||
"addVerifier": "添加核销员",
|
||||
"verifierDeleteTips": "确定要删除该核销员吗?",
|
||||
"memberInfo": "会员信息",
|
||||
"memberIdPlaceholder": "请选择会员",
|
||||
"member": "会员",
|
||||
"searchPlaceholder": "请输入会员昵称搜索"
|
||||
}
|
||||
@ -3,6 +3,6 @@
|
||||
"type": "协议类型",
|
||||
"titlePlaceholder": "请输入协议标题",
|
||||
"contentPlaceholder": "请填写协议内容",
|
||||
"contentMaxTips": "协议内容字符数应在5~100000之间",
|
||||
"contentMaxTips": "协议内容字符数应在5~10000之间",
|
||||
"content": "内容"
|
||||
}
|
||||
|
||||
@ -1,35 +1,39 @@
|
||||
{
|
||||
"websiteInfo":"后台设置",
|
||||
"contactAddress":"联系地址",
|
||||
"siteName": "站点名称",
|
||||
"keywords": "网站关键字",
|
||||
"logo": "长方形Logo",
|
||||
"desc": "网站简介",
|
||||
"province": "省",
|
||||
"city": "市",
|
||||
"district": "区/县",
|
||||
"selectAddress": "请选择地址",
|
||||
"address": "详细地址",
|
||||
"phone": "客服电话",
|
||||
"businessHours": "营业时间",
|
||||
"contactAddressPlaceholder":"联系地址",
|
||||
"siteNamePlaceholder": "站点名称",
|
||||
"keywordsPlaceholder": "网站关键字",
|
||||
"descPlaceholder": "网站简介",
|
||||
"addressPlaceholder": "详细地址",
|
||||
"phonePlaceholder": "客服电话",
|
||||
"businessHoursPlaceholder": "营业时间",
|
||||
"businessHoursTips": "例:上午9:00-12:00,下午2:00-6:00",
|
||||
"frontEndInfo": "前台设置",
|
||||
"frontEndName": "前台名称",
|
||||
"frontEndNamePlaceholder": "请输入前台名称",
|
||||
"frontEndLogo": "前台Logo",
|
||||
"icon": "正方形Logo",
|
||||
"serviceInformation": "服务信息",
|
||||
"wechatCode": "公众号二维码",
|
||||
"customerServiceCode": "客服二维码",
|
||||
"contactsTel": "联系电话",
|
||||
"contactsTelPlaceholder": "请输入联系电话",
|
||||
"logoPlaceholder": "建议图片尺寸:210*30像素;图片格式:jpg、png、jpeg。",
|
||||
"iconPlaceholder": "建议图片尺寸:100*100像素;图片格式:jpg、png、jpeg。"
|
||||
"websiteInfo": "后台设置",
|
||||
"contactAddress": "联系地址",
|
||||
"siteName": "站点名称",
|
||||
"keywords": "网站关键字",
|
||||
"logo": "长方形Logo",
|
||||
"desc": "网站简介",
|
||||
"province": "省",
|
||||
"city": "市",
|
||||
"district": "区/县",
|
||||
"selectAddress": "请选择地址",
|
||||
"address": "详细地址",
|
||||
"phone": "客服电话",
|
||||
"businessHours": "营业时间",
|
||||
"contactAddressPlaceholder": "联系地址",
|
||||
"siteNamePlaceholder": "站点名称",
|
||||
"keywordsPlaceholder": "网站关键字",
|
||||
"descPlaceholder": "网站简介",
|
||||
"addressPlaceholder": "详细地址",
|
||||
"phonePlaceholder": "客服电话",
|
||||
"businessHoursPlaceholder": "营业时间",
|
||||
"businessHoursTips": "例:上午9:00-12:00,下午2:00-6:00",
|
||||
"frontEndInfo": "前台设置",
|
||||
"frontEndName": "前台名称",
|
||||
"frontEndNamePlaceholder": "请输入前台名称",
|
||||
"frontEndLogo": "前台Logo",
|
||||
"icon": "正方形Logo",
|
||||
"serviceInformation": "服务信息",
|
||||
"wechatCode": "公众号二维码",
|
||||
"customerServiceCode": "客服二维码",
|
||||
"contactsTel": "联系电话",
|
||||
"contactsTelPlaceholder": "请输入联系电话",
|
||||
"logoPlaceholder": "建议图片尺寸:210*30像素;图片格式:jpg、png、jpeg。",
|
||||
"iconPlaceholder": "建议图片尺寸:100*100像素;图片格式:jpg、png、jpeg。",
|
||||
"siteLoginLogo": "站点登录Logo",
|
||||
"siteLoginLogoTips": "站点端登录Logo,建议图片尺寸:132*40像素;图片格式:jpg、png、jpeg。",
|
||||
"siteLoginBgImg": "站点登录背景图",
|
||||
"siteLoginBgImgTips": "站点端登录背景图,建议图片尺寸:1920*1280像素;图片格式:jpg、png、jpeg。"
|
||||
}
|
||||
|
||||
@ -28,6 +28,7 @@
|
||||
"alipayPublicCertPathTips": "上传alipayCertPublicKey文件",
|
||||
"alipayRootCertPathTips": "上传alipayRootCert文件",
|
||||
"operationTip": "温馨提示:打款设置用于会员提现转账,发放红包等场景",
|
||||
"transferTips":"注意:应微信方规定,在2025年1月15日前开通商家转账到零钱服务的商户号可正常使用转账功能,之后开通的不支持使用转账到零钱服务"
|
||||
|
||||
"transferTips":"注意:应微信方规定,在2025年1月15日前开通商家转账到零钱服务的商户号可正常使用转账功能,之后开通的不支持使用转账到零钱服务",
|
||||
"wechatpayPublicCert": "微信支付公钥",
|
||||
"wechatpayPublicCertId": "微信支付公钥ID"
|
||||
}
|
||||
|
||||
28
admin/src/app/lang/zh-cn/tools.backup_records.json
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"manualBackup": "手动备份",
|
||||
"manualBackupTips": "即将开始手动备份您的源码和数据库,为确保备份过程中顺利进行以及数据的完整性,建议您暂停所有相关操作,避免因数据写入或修改导致备份不一致,是否确定继续?",
|
||||
"id": "编号",
|
||||
"content": "内容",
|
||||
"currentVersion": "备份版本",
|
||||
"contentPlaceholder": "请输入内容",
|
||||
"batchDelete": "批量删除",
|
||||
"backupDir": "备份路径",
|
||||
"completeTime": "备份时间",
|
||||
"restore": "恢复",
|
||||
"restoreTips": "此操作将恢复备份的源码和数据库,并且覆盖当前数据。为避免意外损失,请确认已了解此操作的影响,并确保已备份重要信息,是否确定继续?",
|
||||
"deleteTips": "删除记录将会同步删除其备份文件,确定要操作吗?",
|
||||
"batchEmptySelectedTips": "请选择需要批量删除的记录",
|
||||
"restoreTitle": "恢复备份",
|
||||
"backupCompleteTips": "备份成功",
|
||||
"restoreCompleteTips": "恢复成功",
|
||||
"showDialogCloseTips": "任务尚未完成,关闭将会造成数据丢失或系统损坏的影响,是否要继续关闭?",
|
||||
"manualBackupTitle": "手动备份",
|
||||
"checkDirectoryPermissions": "检测目录权限",
|
||||
"backupFiles": "备份文件",
|
||||
"startUpgrade": "开始恢复",
|
||||
"upgradeEnd": "恢复完成",
|
||||
"startBackUp": "开始备份",
|
||||
"backUpEnd": "备份完成",
|
||||
"remark": "备注",
|
||||
"remarkEmpty": "无"
|
||||
}
|
||||
8
admin/src/app/lang/zh-cn/tools.upgrade_records.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"id": "编号",
|
||||
"upgradeName": "内容",
|
||||
"prevVersion": "前一版本",
|
||||
"currentVersion": "版本",
|
||||
"upgradeNamePlaceholder": "请输入内容",
|
||||
"completeTime": "升级时间"
|
||||
}
|
||||
@ -1,11 +1,15 @@
|
||||
{
|
||||
"groupName": "站点套餐",
|
||||
"lastTime": "上次同步时间",
|
||||
"weappVersionUpdate": "小程序同步",
|
||||
"weappVersionUpdateRecord": "小程序同步记录",
|
||||
"createTime": "提交时间",
|
||||
"userVersion": "版本号",
|
||||
"failReason": "失败原因",
|
||||
"updateTips": "版本提交成功之后会自动给已授权的小程序进行同步更新,使用该功能必须要启动消息队列",
|
||||
"seeUpdateRecord": "查看同步记录"
|
||||
"groupName": "站点套餐",
|
||||
"lastTime": "上次同步时间",
|
||||
"weappVersionUpdate": "小程序同步",
|
||||
"weappVersionUpdateRecord": "小程序同步记录",
|
||||
"createTime": "提交时间",
|
||||
"userVersion": "版本号",
|
||||
"failReason": "失败原因",
|
||||
"updateTips": " 1、同步小程序时系统通过已绑定的开发小程序同步至微信第三方平台的普通模板库中。\n 2、同步完成后,系统将自动为站点套餐下已授权的小程序提交代码。\n 3、一键同步功能支持按所有站点套餐进行批量同步,同时也可针对单个站点套餐单独操作。\n 4、使用此功能前,请确保已启动消息队列服务。",
|
||||
"seeUpdateRecord": "查看同步记录",
|
||||
"commitRecord": "同步记录",
|
||||
"oneClickSync": "一键同步",
|
||||
"syncTemplateError": "未能同步到模板库",
|
||||
"templateID": "模板ID"
|
||||
}
|
||||
|
||||
@ -2,47 +2,31 @@
|
||||
<!--授权信息-->
|
||||
<div class="main-container">
|
||||
<el-card class="box-card !border-none" shadow="never" v-if="!loading">
|
||||
|
||||
<div class="flex">
|
||||
<div class="w-[450px] mr-[20px] p-[50px] bg-[var(--el-color-info-light-9)]">
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-page-title">版本信息</span>
|
||||
<div class="flex-1 w-0 flex justify-end">
|
||||
<el-button class="text-[#4C4C4C] w-[78px] h-[32px] !bg-transparent" @click="getFrameworkVersionListFn" v-if="!newVersion || (newVersion && newVersion.version_no == versions)">检测更新</el-button>
|
||||
<el-button class="text-[#4C4C4C] w-[78px] h-[32px]" type="primary" @click="handleUpgrade" v-else>一键升级</el-button>
|
||||
<el-button class="text-[#4C4C4C] w-[78px] h-[32px]" type="primary" @click="handleCloudBuild" :loading="cloudBuildRef?.loading">云编译</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-[30px] flex items-center text-[14px] text-[#797979]">
|
||||
<span>当前版本</span>
|
||||
<span class="text-[26px] ml-[15px] mr-[10px] text-[#656668]">{{versions}}</span>
|
||||
<em class="text-[12px]" v-if="!newVersion || (newVersion && newVersion.version_no == versions)">(当前已是最新版本)</em>
|
||||
<em class="text-[12px] text-[red]" v-else>(最新版本{{ newVersion.version_no }})</em>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-1 justify-between items-center p-[50px] bg-[var(--el-color-info-light-9)]">
|
||||
<div>
|
||||
<div class="text-[#333] text-[18px]">授权信息</div>
|
||||
<div class="ml-[50px] mt-[40px]">
|
||||
<div class="flex flex-col">
|
||||
<div class="flex flex-wrap items-center">
|
||||
<p class="text-page-title mr-[20px]">授权信息</p>
|
||||
<span class="text-[14px] text-[#666]">{{ authinfo.company_name || '--' }}</span>
|
||||
<span class="mr-[6px] text-[14px] text-[#666666] w-[70px] text-right">授权公司:</span>
|
||||
<span class="text-[14px] text-[#333]">{{ authinfo.company_name || "--" }}</span>
|
||||
</div>
|
||||
<div class="mt-[46px] ml-[40px] flex flex-wrap">
|
||||
<span class="text-[14px] mr-[84px]">授权域名<em class="ml-[12px] text-[12px]">{{ authinfo.site_address || '--' }}</em></span>
|
||||
<span class="text-[14px] flex items-center">
|
||||
<span>授权码</span>
|
||||
<em class="ml-[12px] mr-[10px] text-[12px]">{{ authinfo.auth_code ? (isCheck ? authinfo.auth_code : hideAuthCode(authinfo.auth_code)) : '--' }}</em>
|
||||
<el-icon v-if="!isCheck" @click="isCheck = !isCheck" class="text-[12px] cursor-pointer">
|
||||
<div class="flex flex-wrap items-center mt-[20px]">
|
||||
<span class="mr-[6px] text-[14px] text-[#666666] w-[70px] text-right">授权域名:</span>
|
||||
<span class="text-[14px] text-[#333]">{{ authinfo.site_address || "--" }}</span>
|
||||
</div>
|
||||
<div class="flex flex-wrap items-center mt-[20px]">
|
||||
<span class="mr-[6px] text-[14px] text-[#666666] w-[70px] text-right">授权码:</span>
|
||||
<span class="text-[14px] text-[#333]">
|
||||
<span class="mr-[10px]">{{ authinfo.auth_code ? (isCheck ? authinfo.auth_code : hideAuthCode(authinfo.auth_code)) : "--" }}</span>
|
||||
<el-icon v-if="!isCheck" @click="isCheck = !isCheck" class="text-[12px] cursor-pointer text-[#4383F9]">
|
||||
<View />
|
||||
</el-icon>
|
||||
<el-icon v-else @click="isCheck = !isCheck" class="text-[12px] cursor-pointer">
|
||||
<Hide />
|
||||
</el-icon>
|
||||
<el-icon v-else @click="isCheck = !isCheck" class="text-[12px] cursor-pointer text-[#4383F9]"> <Hide /> </el-icon>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-1 flex-wrap justify-end relative">
|
||||
<el-button class="w-[154px] !h-[48px] mt-[8px]" type="primary" @click="authCodeApproveFn">授权码认证</el-button>
|
||||
<div class="mt-[60px] mb-[50px]">
|
||||
<el-button class="w-[150px] !h-[46px] mt-[8px]" type="primary" @click="authCodeApproveFn">授权码认证</el-button>
|
||||
<el-popover ref="getAuthCodeDialog" placement="bottom-start" :width="478" trigger="click" class="mt-[8px]">
|
||||
<div class="px-[18px] py-[8px]">
|
||||
<p class="leading-[32px] text-[14px]">您在官方应用市场购买任意一款应用,即可获得授权码。输入正确授权码认证通过后,即可支持在线升级和其它相关服务</p>
|
||||
@ -52,7 +36,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<template #reference>
|
||||
<el-button class="w-[154px] !h-[48px] mt-[8px] !text-[var(--el-color-primary)] hover:!text-[var(--el-color-primary)] !bg-transparent" plain type="primary">如何获取授权码?</el-button>
|
||||
<el-button class="w-[150px] !h-[46px] mt-[8px] !text-[var(--el-color-primary)] hover:!text-[var(--el-color-primary)] !bg-transparent" plain type="primary">如何获取授权码?</el-button>
|
||||
</template>
|
||||
</el-popover>
|
||||
</div>
|
||||
@ -70,13 +54,13 @@
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<div class="text-sm mt-[10px] text-info">{{ t('authInfoTips') }}</div>
|
||||
<div class="text-sm mt-[10px] text-info">{{ t("authInfoTips") }}</div>
|
||||
|
||||
<div class="mt-[20px]">
|
||||
<el-button type="primary" class="w-full" size="large" :loading="saveLoading" @click="save(formRef)">{{ t('confirm') }}</el-button>
|
||||
<el-button type="primary" class="w-full" size="large" :loading="saveLoading" @click="save(formRef)">{{ t("confirm") }}</el-button>
|
||||
</div>
|
||||
<div class="mt-[10px] text-right">
|
||||
<el-button type="primary" link @click="market">{{ t('notHaveAuth') }}</el-button>
|
||||
<el-button type="primary" link @click="market">{{ t("notHaveAuth") }}</el-button>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-form>
|
||||
@ -84,66 +68,24 @@
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<el-card class="box-card !border-none " shadow="never" v-if="!loading">
|
||||
<div class="text-page-title mb-[20px]">历史版本</div>
|
||||
<el-timeline>
|
||||
<el-timeline-item :timestamp="item['release_time'] + ' 版本:' + item['version_no']" v-for="(item,index) in frameworkVersionList" type="primary" :hollow="true" placement="top" :key="index">
|
||||
<div class="mt-[10px] p-[20px] bg-overlay rounded-md timeline-log-wrap whitespace-pre-wrap" v-if="item['upgrade_log']">
|
||||
<div v-html="item['upgrade_log']"></div>
|
||||
</div>
|
||||
</el-timeline-item>
|
||||
</el-timeline>
|
||||
</el-card>
|
||||
|
||||
<upgrade ref="upgradeRef" @cloudbuild="handleCloudBuild"/>
|
||||
<cloud-build ref="cloudBuildRef" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref, computed } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { getVersions } from '@/app/api/auth'
|
||||
import { getAuthInfo, setAuthInfo, getFrameworkVersionList } from '@/app/api/module'
|
||||
import { ElMessageBox, FormInstance, FormRules,ElMessage } from 'element-plus'
|
||||
import Upgrade from '@/app/components/upgrade/index.vue'
|
||||
import CloudBuild from '@/app/components/cloud-build/index.vue'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import { reactive, ref } from "vue"
|
||||
import { t } from "@/lang"
|
||||
import { getVersions } from "@/app/api/auth"
|
||||
import { getAuthInfo, setAuthInfo } from "@/app/api/module"
|
||||
import { FormInstance, FormRules } from "element-plus"
|
||||
import { cloneDeep } from "lodash-es"
|
||||
|
||||
const upgradeRef = ref<any>(null)
|
||||
const cloudBuildRef = ref<any>(null)
|
||||
const getAuthCodeDialog: Record<string, any> | null = ref(null)
|
||||
|
||||
const authCodeApproveDialog = ref(false)
|
||||
const isCheck = ref(false)
|
||||
const frameworkVersionList = ref([])
|
||||
|
||||
const checkVersion = ref(false)
|
||||
const getFrameworkVersionListFn = () => {
|
||||
getFrameworkVersionList().then(({ data }) => {
|
||||
frameworkVersionList.value = data
|
||||
if (checkVersion.value) {
|
||||
if (!newVersion.value || (newVersion.value && newVersion.value.version_no == versions.value)) {
|
||||
ElMessage({
|
||||
message: t('versionTips'),
|
||||
type: 'success'
|
||||
})
|
||||
}
|
||||
} else {
|
||||
checkVersion.value = true
|
||||
}
|
||||
})
|
||||
}
|
||||
getFrameworkVersionListFn()
|
||||
|
||||
const newVersion:any = computed(() => {
|
||||
return frameworkVersionList.value.length ? frameworkVersionList.value[0] : null
|
||||
})
|
||||
|
||||
const hideAuthCode = (res:any) => {
|
||||
const hideAuthCode = (res: any) => {
|
||||
const authCode = cloneDeep(res)
|
||||
const data = authCode.slice(0, authCode.length / 2) + authCode.slice(authCode.length / 2, authCode.length - 1).replace(/./g, '*')
|
||||
const data = authCode.slice(0, authCode.length / 2) + authCode.slice(authCode.length / 2, authCode.length - 1).replace(/./g, "*")
|
||||
return data
|
||||
}
|
||||
|
||||
@ -152,15 +94,15 @@ const authCodeApproveFn = () => {
|
||||
}
|
||||
|
||||
interface AuthInfo {
|
||||
company_name: string,
|
||||
site_address: string,
|
||||
company_name: string
|
||||
site_address: string
|
||||
auth_code: string
|
||||
}
|
||||
|
||||
const authinfo = ref<AuthInfo>({
|
||||
company_name: '',
|
||||
site_address: '',
|
||||
auth_code: ''
|
||||
company_name: "",
|
||||
site_address: "",
|
||||
auth_code: ""
|
||||
})
|
||||
const loading = ref(true)
|
||||
const saveLoading = ref(false)
|
||||
@ -180,25 +122,21 @@ const checkAppMange = () => {
|
||||
checkAppMange()
|
||||
|
||||
const formData = reactive<Record<string, string>>({
|
||||
auth_code: '',
|
||||
auth_secret: ''
|
||||
auth_code: "",
|
||||
auth_secret: ""
|
||||
})
|
||||
const formRef = ref<FormInstance>()
|
||||
|
||||
// 表单验证规则
|
||||
const formRules = reactive<FormRules>({
|
||||
auth_code: [
|
||||
{ required: true, message: t('authCodePlaceholder'), trigger: 'blur' }
|
||||
],
|
||||
auth_secret: [
|
||||
{ required: true, message: t('authSecretPlaceholder'), trigger: 'blur' }
|
||||
]
|
||||
auth_code: [{ required: true, message: t("authCodePlaceholder"), trigger: "blur" }],
|
||||
auth_secret: [{ required: true, message: t("authSecretPlaceholder"), trigger: "blur" }]
|
||||
})
|
||||
|
||||
const save = async (formEl: FormInstance | undefined) => {
|
||||
const save = async(formEl: FormInstance | undefined) => {
|
||||
if (saveLoading.value || !formEl) return
|
||||
|
||||
await formEl.validate(async (valid) => {
|
||||
await formEl.validate(async(valid) => {
|
||||
if (valid) {
|
||||
saveLoading.value = true
|
||||
|
||||
@ -214,47 +152,16 @@ const save = async (formEl: FormInstance | undefined) => {
|
||||
}
|
||||
|
||||
const market = () => {
|
||||
window.open('https://www.niucloud.com/app')
|
||||
window.open("https://www.niucloud.com/app")
|
||||
}
|
||||
|
||||
const versions = ref('')
|
||||
const versions = ref("")
|
||||
const getVersionsInfo = () => {
|
||||
getVersions().then(res => {
|
||||
getVersions().then((res) => {
|
||||
versions.value = res.data.version.version
|
||||
})
|
||||
}
|
||||
getVersionsInfo()
|
||||
|
||||
/**
|
||||
* 升级
|
||||
*/
|
||||
const handleUpgrade = () => {
|
||||
if (!authinfo.value.auth_code) {
|
||||
authCodeApproveFn()
|
||||
return
|
||||
}
|
||||
upgradeRef.value?.open()
|
||||
}
|
||||
|
||||
const handleCloudBuild = () => {
|
||||
if (!authinfo.value.auth_code) {
|
||||
authCodeApproveFn()
|
||||
return
|
||||
}
|
||||
if (cloudBuildRef.value.cloudBuildTask) {
|
||||
cloudBuildRef.value?.open()
|
||||
return
|
||||
}
|
||||
ElMessageBox.confirm(t('cloudBuildTips'), t('warning'),
|
||||
{
|
||||
confirmButtonText: t('confirm'),
|
||||
cancelButtonText: t('cancel'),
|
||||
type: 'warning'
|
||||
}
|
||||
).then(() => {
|
||||
cloudBuildRef.value?.open()
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
@ -23,7 +23,7 @@
|
||||
<div class="flex flex-col justify-between w-[180px]">
|
||||
<div class="text-[14px] flex items-center">
|
||||
<span class="app-text max-w-[170px]">{{ childItem.title }}</span>
|
||||
<span class="iconfont iconxiaochengxu2 text-[#00b240] ml-[4px] !text-[14px]"></span>
|
||||
<!-- <span class="iconfont iconxiaochengxu2 text-[#00b240] ml-[4px] !text-[14px]"></span>-->
|
||||
</div>
|
||||
<!-- <el-icon color="#666">
|
||||
<QuestionFilled />
|
||||
@ -68,7 +68,6 @@ const getAppList = async () => {
|
||||
getAppList()
|
||||
|
||||
const toLink = (item: any) => {
|
||||
console.log('tol', item)
|
||||
if (item.url) {
|
||||
router.push(item.url)
|
||||
} else {
|
||||
|
||||
195
admin/src/app/views/app/upgrade.vue
Normal file
@ -0,0 +1,195 @@
|
||||
<template>
|
||||
<!--授权信息-->
|
||||
<div class="main-container">
|
||||
<el-card class="box-card !border-none" shadow="never" v-if="newVersion">
|
||||
<div>
|
||||
<div class="mx-[20px] my-[20px]">
|
||||
<div class="title text-[18px]">版本信息</div>
|
||||
<div class="text-[18px] text-center mb-[7px] mt-[40px]">系统当前版本:v{{ version }}({{ versionCode }})</div>
|
||||
<div class="text-center text-[#666] text-[14px]" v-if="!newVersion || (newVersion && newVersion.version_no == version)">
|
||||
<span>当前已是最新版本,无需升级</span>
|
||||
<span class="text-[14px] text-primary ml-[10px] cursor-pointer" @click="openUpgrade">更新说明</span>
|
||||
</div>
|
||||
<div class="text-[#666] text-[14px] text-center" v-else>
|
||||
当前系统最新版本为 <span class="text-[18px] text-[#FF4D01]">v{{ newVersion.version_no }}</span>
|
||||
<span class="text-[14px] text-primary ml-[10px]" style="cursor: pointer" @click="openUpgrade">更新说明</span>
|
||||
</div>
|
||||
<div class="mt-[30px] flex justify-center items-center">
|
||||
<el-button class="text-[#4C4C4C] w-[150px] !h-[44px]" type="primary" :loading="loading" @click="handleUpgrade" v-if="!(!newVersion || (newVersion && newVersion.version_no == version))">一键升级</el-button>
|
||||
<el-button class="text-[#4C4C4C] w-[130px] !h-[44px]" @click="upgradeRecord">升级记录</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<el-dialog v-model="authCodeApproveDialog" title="授权码认证" width="400px">
|
||||
<el-form :model="formData" label-width="0" ref="formRef" :rules="formRules" class="page-form">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<el-form-item prop="auth_code">
|
||||
<el-input v-model.trim="formData.auth_code" :placeholder="t('authCodePlaceholder')" class="input-width" clearable size="large" />
|
||||
</el-form-item>
|
||||
|
||||
<div class="mt-[20px]">
|
||||
<el-form-item prop="auth_secret">
|
||||
<el-input v-model.trim="formData.auth_secret" clearable :placeholder="t('authSecretPlaceholder')" class="input-width" size="large" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<div class="text-sm mt-[10px] text-info">{{ t("authInfoTips") }}</div>
|
||||
|
||||
<div class="mt-[20px]">
|
||||
<el-button type="primary" class="w-full" size="large" :loading="saveLoading" @click="save(formRef)">{{ t("confirm") }}</el-button>
|
||||
</div>
|
||||
<div class="mt-[10px] text-right">
|
||||
<el-button type="primary" link @click="market">{{ t("notHaveAuth") }}</el-button>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-form>
|
||||
</el-dialog>
|
||||
|
||||
<upgrade ref="upgradeRef" />
|
||||
<upgrade-log ref="upgradeLogRef" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed, reactive } from "vue"
|
||||
import { t } from "@/lang"
|
||||
import { getVersions } from "@/app/api/auth"
|
||||
import { getAuthInfo, getFrameworkVersionList, setAuthInfo } from "@/app/api/module"
|
||||
import { ElMessage, FormInstance, FormRules } from "element-plus"
|
||||
import { useRouter } from "vue-router"
|
||||
import Upgrade from "@/app/components/upgrade/index.vue"
|
||||
import UpgradeLog from "@/app/components/upgrade-log/index.vue"
|
||||
|
||||
const upgradeRef = ref<any>(null)
|
||||
const upgradeLogRef = ref<any>(null)
|
||||
const authCodeApproveDialog = ref(false)
|
||||
const frameworkVersionList = ref([])
|
||||
|
||||
const checkVersion = ref(false)
|
||||
|
||||
const formData = reactive<Record<string, string>>({
|
||||
auth_code: '',
|
||||
auth_secret: ''
|
||||
})
|
||||
const formRef = ref<FormInstance>()
|
||||
|
||||
// 表单验证规则
|
||||
const formRules = reactive<FormRules>({
|
||||
auth_code: [{ required: true, message: t('authCodePlaceholder'), trigger: 'blur' }],
|
||||
auth_secret: [{ required: true, message: t('authSecretPlaceholder'), trigger: 'blur' }]
|
||||
})
|
||||
|
||||
const saveLoading = ref(false)
|
||||
|
||||
const save = async(formEl: FormInstance | undefined) => {
|
||||
if (saveLoading.value || !formEl) return
|
||||
|
||||
await formEl.validate(async (valid) => {
|
||||
if (valid) {
|
||||
saveLoading.value = true
|
||||
|
||||
setAuthInfo(formData).then(() => {
|
||||
saveLoading.value = false
|
||||
checkAppMange()
|
||||
}).catch(() => {
|
||||
saveLoading.value = false
|
||||
authCodeApproveDialog.value = false
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const getFrameworkVersionListFn = () => {
|
||||
getFrameworkVersionList().then(({ data }) => {
|
||||
frameworkVersionList.value = data
|
||||
if (checkVersion.value) {
|
||||
if (!newVersion.value || (newVersion.value && newVersion.value.version_no == version.value)) {
|
||||
ElMessage({
|
||||
message: t('versionTips'),
|
||||
type: 'success'
|
||||
})
|
||||
}
|
||||
} else {
|
||||
checkVersion.value = true
|
||||
}
|
||||
})
|
||||
}
|
||||
getFrameworkVersionListFn()
|
||||
|
||||
const newVersion: any = computed(() => {
|
||||
return frameworkVersionList.value.length ? frameworkVersionList.value[0] : null
|
||||
})
|
||||
|
||||
const authCodeApproveFn = () => {
|
||||
authCodeApproveDialog.value = true
|
||||
}
|
||||
|
||||
const version = ref('')
|
||||
const versionCode = ref('')
|
||||
|
||||
const getVersionsInfo = () => {
|
||||
getVersions().then((res) => {
|
||||
version.value = res.data.version.version
|
||||
versionCode.value = res.data.version.code
|
||||
})
|
||||
}
|
||||
getVersionsInfo()
|
||||
|
||||
interface AuthInfo {
|
||||
company_name: string
|
||||
site_address: string
|
||||
auth_code: string
|
||||
}
|
||||
|
||||
const authInfo = ref<AuthInfo>({
|
||||
company_name: '',
|
||||
site_address: '',
|
||||
auth_code: ''
|
||||
})
|
||||
|
||||
const repeat = ref(false)
|
||||
const loading = ref(false)
|
||||
|
||||
/**
|
||||
* 升级
|
||||
*/
|
||||
const handleUpgrade = () => {
|
||||
if (!authInfo.value.auth_code) {
|
||||
authCodeApproveFn()
|
||||
return
|
||||
}
|
||||
if (repeat.value) return
|
||||
repeat.value = true
|
||||
loading.value = true
|
||||
upgradeRef.value?.open('', () => {
|
||||
repeat.value = false
|
||||
loading.value = false;
|
||||
})
|
||||
}
|
||||
|
||||
const checkAppMange = () => {
|
||||
getAuthInfo().then((res) => {
|
||||
if (res.data.data && res.data.data.length != 0) {
|
||||
authInfo.value = res.data.data
|
||||
authCodeApproveDialog.value = false
|
||||
}
|
||||
}).catch(() => {
|
||||
authCodeApproveDialog.value = false
|
||||
})
|
||||
}
|
||||
|
||||
checkAppMange()
|
||||
|
||||
const router = useRouter()
|
||||
const upgradeRecord = () => {
|
||||
router.push('/admin/tools/upgrade_records')
|
||||
}
|
||||
|
||||
const openUpgrade = () => {
|
||||
upgradeLogRef.value?.open()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@ -84,8 +84,8 @@ getMenuList()
|
||||
// 重置菜单
|
||||
const refreshMenu = () => {
|
||||
ElMessageBox.confirm(h('div', null, [
|
||||
h('p', null, t('initializeMenuTipsOne')),
|
||||
h('p', null, t('initializeMenuTipsTwo')),
|
||||
h('p', null, t('initializeMenuTipsOne')),
|
||||
h('p', null, t('initializeMenuTipsTwo')),
|
||||
]), t('warning'),
|
||||
{
|
||||
confirmButtonText: t('confirm'),
|
||||
@ -97,8 +97,8 @@ const refreshMenu = () => {
|
||||
location.reload()
|
||||
}).catch(() => {
|
||||
})
|
||||
}).catch(()=>{})
|
||||
|
||||
}).catch(() => {
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -132,8 +132,8 @@ getMenuList()
|
||||
// 重置菜单
|
||||
const refreshMenu = () => {
|
||||
ElMessageBox.confirm(h('div', null, [
|
||||
h('p', null, t('initializeMenuTipsOne')),
|
||||
h('p', null, t('initializeMenuTipsTwo')),
|
||||
h('p', null, t('initializeMenuTipsOne')),
|
||||
h('p', null, t('initializeMenuTipsTwo')),
|
||||
]), t('warning'),
|
||||
{
|
||||
confirmButtonText: t('confirm'),
|
||||
@ -143,9 +143,10 @@ const refreshMenu = () => {
|
||||
).then(() => {
|
||||
menuRefresh({}).then(res => {
|
||||
location.reload()
|
||||
}).catch(() => {})
|
||||
}).catch(()=>{})
|
||||
|
||||
}).catch(() => {
|
||||
})
|
||||
}).catch(() => {
|
||||
})
|
||||
}
|
||||
/**
|
||||
* 添加菜单
|
||||
|
||||
@ -102,7 +102,6 @@ const router = useRouter()
|
||||
const pageName = route.meta.title
|
||||
|
||||
const activeName = ref('/channel/aliapp')
|
||||
const active = ref(2)
|
||||
const qrCode = ref<string>('')
|
||||
onMounted(async () => {
|
||||
const res = await getAliappConfig()
|
||||
|
||||
@ -116,7 +116,6 @@ const router = useRouter()
|
||||
const pageName = route.meta.title
|
||||
|
||||
const activeName = ref('/channel/weapp')
|
||||
const active = ref(2)
|
||||
const qrCode = ref('')
|
||||
const weappConfig = ref({})
|
||||
const oplatformConfig = ref({})
|
||||
|
||||
@ -106,7 +106,6 @@
|
||||
import { computed, reactive, ref } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import Test from '@/utils/test'
|
||||
import SettingList from './setting-list.vue'
|
||||
import { getWeappPrivacySetting, setWeappPrivacySetting } from '@/app/api/weapp'
|
||||
|
||||
|
||||
@ -50,7 +50,7 @@
|
||||
</el-form-item>
|
||||
</el-card>
|
||||
|
||||
<el-card class="box-card !border-none mt-[15px]" shadow="never">
|
||||
<el-card class="box-card !border-none mt-[15px]" shadow="never" v-show="!formData.is_authorization">
|
||||
<h3 class="panel-title !text-sm">{{ t('theServerSetting') }}</h3>
|
||||
|
||||
<el-form-item label="URL">
|
||||
@ -234,10 +234,10 @@ const formRules = computed(() => {
|
||||
{ required: !formData.is_authorization, message: t('appSecretPlaceholder'), trigger: 'blur' }
|
||||
],
|
||||
token: [
|
||||
{ required: true, message: t('tokenPlaceholder'), trigger: 'blur' }
|
||||
{ required: !formData.is_authorization, message: t('tokenPlaceholder'), trigger: 'blur' }
|
||||
],
|
||||
encoding_aes_key: [
|
||||
{ required: true, message: t('encodingAesKeyPlaceholder'), trigger: 'blur' }
|
||||
{ required: !formData.is_authorization, message: t('encodingAesKeyPlaceholder'), trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
})
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
<template>
|
||||
<!--配置教程-->
|
||||
<div class="main-container">
|
||||
<div class="main-container">
|
||||
|
||||
<el-card class="card !border-none" shadow="never">
|
||||
<el-page-header :content="pageName" :icon="ArrowLeft" @back="back()" />
|
||||
</el-card>
|
||||
<el-card class="card !border-none" shadow="never">
|
||||
<el-page-header :content="pageName" :icon="ArrowLeft" @back="back()" />
|
||||
</el-card>
|
||||
|
||||
<el-card class="box-card mt-[15px] !border-none" shadow="never">
|
||||
<el-card class="box-card mt-[15px] !border-none" shadow="never">
|
||||
<div class="flex">
|
||||
<div class="min-w-[60px]">
|
||||
<span class="flex justify-center items-center block w-[40px] h-[40px] border-[1px] border-primary rounded-[999px] text-primary">1</span>
|
||||
@ -51,8 +51,8 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
||||
@ -104,7 +104,6 @@ const router = useRouter()
|
||||
const pageName = route.meta.title
|
||||
|
||||
const activeName = ref('/channel/wechat')
|
||||
const active = ref(2)
|
||||
const qrcode = ref('')
|
||||
const wechatConfig = ref({})
|
||||
const oplatformConfig = ref({})
|
||||
|
||||
@ -24,11 +24,7 @@
|
||||
</div>
|
||||
<div class="py-[20px] px-[30px] h-[350px]">
|
||||
<div v-if="formData.msgtype == 'text'">
|
||||
<el-input
|
||||
v-model.trim="formData.text.content" :rows="5" type="textarea" placeholder="" maxlength="600" :show-word-limit="true"
|
||||
resize="none"
|
||||
input-style="box-shadow: none;height:300px"
|
||||
/>
|
||||
<el-input v-model.trim="formData.text.content" :rows="5" type="textarea" placeholder="" maxlength="600" :show-word-limit="true" resize="none" input-style="box-shadow: none;height:300px" />
|
||||
</div>
|
||||
<div v-if="formData.msgtype == 'image'" class="flex w-full h-full justify-center items-center image-media">
|
||||
<div class="w-full h-full" v-if="formData.image.url">
|
||||
|
||||
@ -14,7 +14,9 @@
|
||||
</upload-media>
|
||||
</div>
|
||||
<div class="flex" v-else>
|
||||
<el-button type="primary" :loading="syncLoading" @click="syncWechatNews">{{ syncLoading ? '同步中' : '同步微信图文'}}</el-button>
|
||||
<el-button type="primary" :loading="syncLoading" @click="syncWechatNews">
|
||||
{{ syncLoading ? '同步中' : '同步微信图文' }}
|
||||
</el-button>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@ -23,8 +25,10 @@
|
||||
<!-- 素材管理 -->
|
||||
<div v-if="attachment.data.length">
|
||||
<div class="flex flex-wrap" v-if="prop.type != 'news'">
|
||||
<div class="attachment-item mr-[10px] mb-[10px] w-[120px]" v-for="(item, index) in attachment.data" :key="index" @click="selectedFile = item">
|
||||
<div class="attachment-wrap w-full rounded cursor-pointer overflow-hidden relative flex items-center justify-center h-[120px]">
|
||||
<div class="attachment-item mr-[10px] mb-[10px] w-[120px]"
|
||||
v-for="(item, index) in attachment.data" :key="index" @click="selectedFile = item">
|
||||
<div
|
||||
class="attachment-wrap w-full rounded cursor-pointer overflow-hidden relative flex items-center justify-center h-[120px]">
|
||||
<el-image :src="img(item.value)" fit="contain" v-if="type == 'image'" :preview-src-list="item.image_list" />
|
||||
<video :src="img(item.value)" v-else-if="type == 'video'"></video>
|
||||
<div class="absolute z-[1] flex items-center justify-center w-full h-full inset-0 bg-black bg-opacity-60" v-show="selectedFile.id == item.id">
|
||||
@ -34,12 +38,14 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="relative" ref="waterfallContainerRef" v-else>
|
||||
<div ref="waterfallItemRef" class="absolute attachment-item mr-[10px] mb-[10px] w-[280px] rounded-lg overflow-hidden border border-color" v-for="(item, index) in attachment.data"
|
||||
<div ref="waterfallItemRef"
|
||||
class="absolute attachment-item mr-[10px] mb-[10px] w-[280px] rounded-lg overflow-hidden border border-color"
|
||||
v-for="(item, index) in attachment.data"
|
||||
:style="{ left: listPosition[index] ? listPosition[index].left : '', top: listPosition[index] ? listPosition[index].top : '' }"
|
||||
:key="index" @click="selectedFile = item">
|
||||
<div class="relative">
|
||||
<div class="w-full h-[130px] relative">
|
||||
<el-image :src="item.value.news_item[0].thumb_url" class="w-full h-full"/>
|
||||
<el-image :src="item.value.news_item[0].thumb_url" class="w-full h-full" />
|
||||
<div class="absolute left-0 bottom-0 p-[10px] w-full truncate text-white leading-none" v-if="item.value.news_item.length > 1">
|
||||
{{ item.value.news_item[0].title }}
|
||||
</div>
|
||||
@ -47,18 +53,14 @@
|
||||
<div v-if="item.value.news_item.length > 1">
|
||||
<template v-for="(newsItem, newsIndex) in item.value.news_item">
|
||||
<div class="px-[15px] py-[10px] flex" :class="{'border-b border-color' : newsIndex < item.value.news_item.length - 1 }" v-if="newsIndex > 0">
|
||||
<div class="flex-1 w-0 truncate">
|
||||
{{ newsItem.title }}
|
||||
</div>
|
||||
<div class="flex-1 w-0 truncate">{{ newsItem.title }}</div>
|
||||
<div class="w-[50px] h-[50px] ml-[10px]">
|
||||
<el-image :src="newsItem.thumb_url" class="w-full h-full"/>
|
||||
<el-image :src="newsItem.thumb_url" class="w-full h-full" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class="px-[15px] py-[10px]" v-else>
|
||||
{{ item.value.news_item[0].title }}
|
||||
</div>
|
||||
<div class="px-[15px] py-[10px]" v-else>{{ item.value.news_item[0].title }}</div>
|
||||
<div class="absolute z-[1] flex items-center justify-center w-full h-full inset-0 bg-black bg-opacity-60" v-show="selectedFile.id == item.id">
|
||||
<icon name="element Select" color="#fff" size="40px" />
|
||||
</div>
|
||||
@ -75,9 +77,9 @@
|
||||
<el-col span="24">
|
||||
<div class="flex h-full justify-end items-center">
|
||||
<el-pagination v-model:current-page="attachment.page" :small="true"
|
||||
v-model:page-size="attachment.limit" :page-sizes="[10, 20, 30, 40, 60]"
|
||||
layout="total, sizes, prev, pager, next, jumper" :total="attachment.total"
|
||||
@size-change="getAttachmentList()" @current-change="getAttachmentList" />
|
||||
v-model:page-size="attachment.limit" :page-sizes="[10, 20, 30, 40, 60]"
|
||||
layout="total, sizes, prev, pager, next, jumper" :total="attachment.total"
|
||||
@size-change="getAttachmentList()" @current-change="getAttachmentList" />
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@ -94,118 +96,118 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref, nextTick } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import UploadMedia from './upload-media.vue'
|
||||
import { img, debounce } from '@/utils/common'
|
||||
import { getMediaList, syncNews } from '@/app/api/wechat'
|
||||
import { reactive, ref, nextTick } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import UploadMedia from './upload-media.vue'
|
||||
import { img, debounce } from '@/utils/common'
|
||||
import { getMediaList, syncNews } from '@/app/api/wechat'
|
||||
|
||||
const prop = defineProps({
|
||||
type: {
|
||||
type: String,
|
||||
default: 'image'
|
||||
}
|
||||
})
|
||||
const prop = defineProps({
|
||||
type: {
|
||||
type: String,
|
||||
default: 'image'
|
||||
}
|
||||
})
|
||||
|
||||
const showDialog = ref(false)
|
||||
const showDialog = ref(false)
|
||||
|
||||
const openDialog = () => {
|
||||
const openDialog = () => {
|
||||
prop.type == 'news' && waterfall()
|
||||
showDialog.value = true
|
||||
}
|
||||
|
||||
const attachment: Record<string, any> = reactive({
|
||||
loading: true,
|
||||
page: 1,
|
||||
total: 0,
|
||||
limit: 10,
|
||||
data: []
|
||||
})
|
||||
|
||||
/**
|
||||
* 查询素材
|
||||
*/
|
||||
const getAttachmentList = (page: number = 1) => {
|
||||
attachment.loading = true
|
||||
attachment.page = page
|
||||
getMediaList({
|
||||
page: attachment.page,
|
||||
limit: attachment.limit,
|
||||
type: prop.type
|
||||
}).then(res => {
|
||||
attachment.data = res.data.data
|
||||
attachment.total = res.data.total
|
||||
attachment.loading = false
|
||||
prop.type == 'news' && waterfall()
|
||||
showDialog.value = true
|
||||
}
|
||||
|
||||
const attachment: Record<string, any> = reactive({
|
||||
loading: true,
|
||||
page: 1,
|
||||
total: 0,
|
||||
limit: 10,
|
||||
data: []
|
||||
}).catch(() => {
|
||||
attachment.loading = false
|
||||
})
|
||||
}
|
||||
getAttachmentList()
|
||||
|
||||
/**
|
||||
* 查询素材
|
||||
*/
|
||||
const getAttachmentList = (page: number = 1) => {
|
||||
attachment.loading = true
|
||||
attachment.page = page
|
||||
getMediaList({
|
||||
page: attachment.page,
|
||||
limit: attachment.limit,
|
||||
type: prop.type
|
||||
}).then(res => {
|
||||
attachment.data = res.data.data
|
||||
attachment.total = res.data.total
|
||||
attachment.loading = false
|
||||
prop.type == 'news' && waterfall()
|
||||
}).catch(() => {
|
||||
attachment.loading = false
|
||||
})
|
||||
}
|
||||
getAttachmentList()
|
||||
const emits = defineEmits(['success'])
|
||||
const selectedFile: Record<string, any> = ref({})
|
||||
|
||||
const emits = defineEmits(['success'])
|
||||
const selectedFile: Record<string, any> = ref({})
|
||||
const confirm = () => {
|
||||
emits('success', selectedFile.value)
|
||||
}
|
||||
|
||||
const confirm = () => {
|
||||
emits('success', selectedFile.value)
|
||||
}
|
||||
const syncLoading = ref(false)
|
||||
const syncWechatNews = () => {
|
||||
if (syncLoading.value) return
|
||||
syncLoading.value = true
|
||||
|
||||
const syncLoading = ref(false)
|
||||
const syncWechatNews = () => {
|
||||
if (syncLoading.value) return
|
||||
syncLoading.value = true
|
||||
syncNews().then(() => {
|
||||
syncLoading.value = false
|
||||
getAttachmentList()
|
||||
}).catch(() => {
|
||||
syncLoading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
syncNews().then(() => {
|
||||
syncLoading.value = false
|
||||
getAttachmentList()
|
||||
}).catch(() => {
|
||||
syncLoading.value = false
|
||||
})
|
||||
}
|
||||
const meta = document.createElement('meta')
|
||||
meta.content = 'same-origin'
|
||||
meta.name = 'referrer'
|
||||
document.getElementsByTagName('head')[0].appendChild(meta)
|
||||
|
||||
const meta = document.createElement('meta')
|
||||
meta.content = 'same-origin'
|
||||
meta.name = 'referrer'
|
||||
document.getElementsByTagName('head')[0].appendChild(meta)
|
||||
// 瀑布流计算
|
||||
const waterfallContainerRef = ref(null)
|
||||
const waterfallItemRef = ref([])
|
||||
const listPosition = ref([])
|
||||
const waterfall = debounce(() => {
|
||||
nextTick(() => {
|
||||
const containerWidth = waterfallContainerRef.value.clientWidth
|
||||
const column = parseInt(containerWidth / 292)
|
||||
const heights = []
|
||||
const positions = []
|
||||
|
||||
// 瀑布流计算
|
||||
const waterfallContainerRef = ref(null)
|
||||
const waterfallItemRef = ref([])
|
||||
const listPosition = ref([])
|
||||
const waterfall = debounce(() => {
|
||||
nextTick(() => {
|
||||
const containerWidth = waterfallContainerRef.value.clientWidth
|
||||
const column = parseInt(containerWidth / 292)
|
||||
const heights = []
|
||||
const positions = []
|
||||
|
||||
waterfallItemRef.value.forEach((item, i) => {
|
||||
if (i < column) {
|
||||
const position = {}
|
||||
position.top = '0px'
|
||||
if (i % column == 0) {
|
||||
position.left = item.clientWidth * i + "px"
|
||||
} else {
|
||||
position.left = item.clientWidth * i + (i % column * 10) + "px"
|
||||
}
|
||||
positions[i] = position
|
||||
heights[i] = item.clientHeight + 10
|
||||
waterfallItemRef.value.forEach((item, i) => {
|
||||
if (i < column) {
|
||||
const position = {}
|
||||
position.top = '0px'
|
||||
if (i % column == 0) {
|
||||
position.left = item.clientWidth * i + "px"
|
||||
} else {
|
||||
let minHeight = Math.min(...heights) // 找到第一列的最小高度
|
||||
let minIndex = heights.findIndex(item => item === minHeight) // 找到最小高度的索引
|
||||
let position = {}
|
||||
position.top = minHeight + 10 + "px"
|
||||
position.left = positions[minIndex].left
|
||||
positions[i] = position
|
||||
heights[minIndex] += item.clientHeight + 10
|
||||
position.left = item.clientWidth * i + (i % column * 10) + "px"
|
||||
}
|
||||
})
|
||||
listPosition.value = positions
|
||||
positions[i] = position
|
||||
heights[i] = item.clientHeight + 10
|
||||
} else {
|
||||
let minHeight = Math.min(...heights) // 找到第一列的最小高度
|
||||
let minIndex = heights.findIndex(item => item === minHeight) // 找到最小高度的索引
|
||||
let position = {}
|
||||
position.top = minHeight + 10 + "px"
|
||||
position.left = positions[minIndex].left
|
||||
positions[i] = position
|
||||
heights[minIndex] += item.clientHeight + 10
|
||||
}
|
||||
})
|
||||
}, 800)
|
||||
listPosition.value = positions
|
||||
})
|
||||
}, 800)
|
||||
|
||||
// 重新布局,以适应窗口变化
|
||||
window.addEventListener('resize', () => waterfall())
|
||||
// 重新布局,以适应窗口变化
|
||||
window.addEventListener('resize', () => waterfall())
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@ -83,8 +83,7 @@
|
||||
<el-form-item :label="t('businessDomain')">
|
||||
<el-input :model-value="wechatStatic.business_domain" placeholder="Please input" class="input-width" :readonly="true">
|
||||
<template #append>
|
||||
<div class="cursor-pointer" @click="copyEvent(wechatStatic.business_domain)">{{ t('copy') }}
|
||||
</div>
|
||||
<div class="cursor-pointer" @click="copyEvent(wechatStatic.business_domain)">{{ t('copy') }}</div>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
@ -92,8 +91,7 @@
|
||||
<el-form-item :label="t('jsSecureDomain')">
|
||||
<el-input :model-value="wechatStatic.js_secure_domain" placeholder="Please input" class="input-width" :readonly="true">
|
||||
<template #append>
|
||||
<div class="cursor-pointer" @click="copyEvent(wechatStatic.business_domain)">{{ t('copy') }}
|
||||
</div>
|
||||
<div class="cursor-pointer" @click="copyEvent(wechatStatic.business_domain)">{{ t('copy') }}</div>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
@ -101,8 +99,7 @@
|
||||
<el-form-item :label="t('webAuthDomain')">
|
||||
<el-input :model-value="wechatStatic.web_auth_domain" placeholder="Please input" class="input-width" :readonly="true">
|
||||
<template #append>
|
||||
<div class="cursor-pointer" @click="copyEvent(wechatStatic.business_domain)">{{ t('copy') }}
|
||||
</div>
|
||||
<div class="cursor-pointer" @click="copyEvent(wechatStatic.business_domain)">{{ t('copy') }}</div>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
|
||||
@ -12,9 +12,7 @@
|
||||
<span class="flex justify-center items-center block w-[40px] h-[40px] border-[1px] border-primary rounded-[999px] text-primary">1</span>
|
||||
</div>
|
||||
<div>
|
||||
<p class="flex items-center text-[14px]">{{ t('writingTipsOne1') }}--<el-button link type="primary"
|
||||
@click="linkEvent">{{ t('writingTipsOne2') }}</el-button>, {{ t('writingTipsOne3') }}<span
|
||||
class="text-primary">URL / Token / EncondingAESKey</span>{{ t('writingTipsOne4') }}</p>
|
||||
<p class="flex items-center text-[14px]">{{ t('writingTipsOne1') }}--<el-button link type="primary" @click="linkEvent">{{ t('writingTipsOne2') }}</el-button>, {{ t('writingTipsOne3') }}<span class="text-primary">URL / Token / EncondingAESKey</span>{{ t('writingTipsOne4') }}</p>
|
||||
<div class="w-[100%] mt-[10px]">
|
||||
<img class="w-[100%]" src="@/app/assets/images/setting/wechat_1.png" />
|
||||
</div>
|
||||
|
||||
@ -83,7 +83,7 @@
|
||||
import { reactive, ref } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { getKeywordsReplyInfo, editKeywordsReply, addKeywordsReply } from '@/app/api/wechat'
|
||||
import { ElMessage, FormInstance, FormRules } from 'element-plus'
|
||||
import { FormInstance, FormRules } from 'element-plus'
|
||||
import { ArrowLeft } from '@element-plus/icons-vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import ReplyForm from '@/app/views/channel/wechat/components/reply-form.vue'
|
||||
|
||||
@ -110,60 +110,6 @@ const setFormData = async (row: any = null) => {
|
||||
loading.value = false
|
||||
}
|
||||
|
||||
// 验证手机号格式
|
||||
const mobileVerify = (rule: any, value: any, callback: any) => {
|
||||
if (value && !/^1[3-9]\d{9}$/.test(value)) {
|
||||
callback(new Error(t('generateMobile')))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
|
||||
// 验证身份证号
|
||||
const idCardVerify = (rule: any, value: any, callback: any) => {
|
||||
if (value && !/^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/.test(value)) {
|
||||
callback(new Error(t('generateIdCard')))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
|
||||
// 验证邮箱号
|
||||
const emailVerify = (rule: any, value: any, callback: any) => {
|
||||
if (value && !/\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/.test(value)) {
|
||||
callback(new Error(t('generateEmail')))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
|
||||
// 验证至少输入1个字符
|
||||
const minInputVerify = (rule: any, value: any, callback: any) => {
|
||||
if (value && !/^\d{0,}$/.test(value)) {
|
||||
callback(new Error(t('generateMin')))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
|
||||
// 验证最多输入150个字符
|
||||
const maxInputVerify = (rule: any, value: any, callback: any) => {
|
||||
if (value && !/^\d{0,150}$/.test(value)) {
|
||||
callback(new Error(t('generateMax')))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
|
||||
// 验证请输入整数
|
||||
const numberVerify = (rule: any, value: any, callback: any) => {
|
||||
if (!Number.isInteger(value)) {
|
||||
callback(new Error(t('generateNumber')))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
showDialog,
|
||||
setFormData
|
||||
|
||||
@ -27,19 +27,15 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed, watch } from 'vue'
|
||||
import { ref, reactive, computed } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { getAreaListByPid } from '@/app/api/sys'
|
||||
import { addMemberAddress } from '@/app/api/member'
|
||||
import { filterNumber } from '@/utils/common'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import { FormRules } from 'element-plus'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import useDiyStore from '@/stores/modules/diy'
|
||||
const diyStore = useDiyStore()
|
||||
|
||||
const dialogThemeVisible = ref(false)
|
||||
let confirmRepeat = false
|
||||
const confirmRepeat = ref(false)
|
||||
const emit = defineEmits(['confirm'])
|
||||
/**
|
||||
* 表单数据
|
||||
@ -73,35 +69,50 @@ const open = (option:any) => {
|
||||
const formRef = ref<FormInstance>()
|
||||
|
||||
// 表单验证规则
|
||||
const formRules = reactive<FormRules>({
|
||||
title: [
|
||||
{ required: true, message: "请输入颜色名称", trigger: 'blur' }
|
||||
],
|
||||
value: [
|
||||
{ required: true, message: "请输入颜色value值", trigger: 'blur' }
|
||||
],
|
||||
label: [
|
||||
{ required: true, message: "请输入颜色key值", trigger: 'blur' },
|
||||
{
|
||||
validator: (rule: any, value: any, callback: any) => {
|
||||
const regex = /^[a-zA-Z0-9-]+$/
|
||||
if (keyArr.indexOf(value) != -1) {
|
||||
callback('新增颜色key值与已存在颜色key值命名重复,请修改命名')
|
||||
} if (!regex.test(value)) {
|
||||
callback('颜色key值只能输入字母、数字和连字符')
|
||||
} else{
|
||||
callback();
|
||||
}
|
||||
},
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
const formRules = computed(() => {
|
||||
return {
|
||||
title: [
|
||||
{ required: true, message: "请输入颜色名称", trigger: 'blur' }
|
||||
],
|
||||
value: [
|
||||
{
|
||||
required: true,
|
||||
validator: (rule: any, value: any, callback: any) => {
|
||||
if (!value) {
|
||||
callback('请输入颜色value值')
|
||||
} else{
|
||||
callback();
|
||||
}
|
||||
},
|
||||
trigger: ['blur', 'change']
|
||||
}
|
||||
],
|
||||
label: [
|
||||
{ required: true, message: "请输入颜色key值", trigger: 'blur' },
|
||||
{
|
||||
validator: (rule: any, value: any, callback: any) => {
|
||||
const regex = /^[a-zA-Z0-9-]+$/
|
||||
if (keyArr.indexOf(value) != -1) {
|
||||
callback('新增颜色key值与已存在颜色key值命名重复,请修改命名')
|
||||
} if (!regex.test(value)) {
|
||||
callback('颜色key值只能输入字母、数字和连字符')
|
||||
} else{
|
||||
callback();
|
||||
}
|
||||
},
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
|
||||
const confirmFn = async (formEl: FormInstance | undefined) => {
|
||||
if (confirmRepeat || !formEl) return
|
||||
await formEl.validate(async (valid) => {
|
||||
if (confirmRepeat.value) return
|
||||
await formRef.value?.validate(async (valid) => {
|
||||
if (confirmRepeat.value) return
|
||||
confirmRepeat.value = true
|
||||
if (valid) {
|
||||
confirmRepeat.value = false
|
||||
emit('confirm', cloneDeep(formData));
|
||||
dialogThemeVisible.value = false;
|
||||
}
|
||||
|
||||
@ -1,102 +1,109 @@
|
||||
<template>
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('titleContent') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]" @submit.prevent>
|
||||
<el-form-item :label="t('selectStyle')" class="flex">
|
||||
<span class="text-primary flex-1 cursor-pointer" @click="showTitleStyle">{{ diyStore.editComponent.titleStyle.title }}</span>
|
||||
<el-icon>
|
||||
<ArrowRight />
|
||||
</el-icon>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('title')" v-if="diyStore.editComponent && diyStore.editComponent.titleStyle && diyStore.editComponent.titleStyle.value != 'style-5'">
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('titleContent') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]" @submit.prevent>
|
||||
<el-form-item :label="t('selectStyle')" class="flex">
|
||||
<span class="text-primary flex-1 cursor-pointer" @click="showTitleStyle">{{ diyStore.editComponent.titleStyle.title }}</span>
|
||||
<el-icon>
|
||||
<ArrowRight />
|
||||
</el-icon>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('title')" v-if="diyStore.editComponent && diyStore.editComponent.titleStyle && diyStore.editComponent.titleStyle.value != 'style-5'">
|
||||
<el-input v-model.trim="diyStore.editComponent.text" :placeholder="t('titlePlaceholder')" clearable maxlength="10" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('image')" v-else>
|
||||
<upload-image v-model="diyStore.editComponent.textImg" :limit="1"/>
|
||||
<upload-image v-model="diyStore.editComponent.textImg" :limit="1" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('link')">
|
||||
<diy-link v-model="diyStore.editComponent.textLink"/>
|
||||
<diy-link v-model="diyStore.editComponent.textLink" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('subTitle')">
|
||||
<el-input v-model.trim="diyStore.editComponent.subTitle.text" :placeholder="t('subTitlePlaceholder')" clearable maxlength="8" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('link')">
|
||||
<diy-link v-model="diyStore.editComponent.subTitle.link"/>
|
||||
<diy-link v-model="diyStore.editComponent.subTitle.link" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-form>
|
||||
|
||||
<el-dialog v-model="showTitleDialog" :title="t('selectStyle')" width="460px">
|
||||
<el-dialog v-model="showTitleDialog" :title="t('selectStyle')" width="460px">
|
||||
|
||||
<div class="flex flex-wrap">
|
||||
<template v-for="(item,index) in titleStyleList" :key="index">
|
||||
<div :class="{ 'border-primary': selectTitleStyle.value == item.value }" @click="changeTitleStyle(item)" class="flex items-center justify-center overflow-hidden w-[200px] h-[100px] mr-[12px] mb-[12px] cursor-pointer border bg-[#eee]">
|
||||
<img :src="img(item.url)" />
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class="flex flex-wrap">
|
||||
<template v-for="(item,index) in titleStyleList" :key="index">
|
||||
<div :class="{ 'border-primary': selectTitleStyle.value == item.value }"
|
||||
@click="changeTitleStyle(item)"
|
||||
class="flex items-center justify-center overflow-hidden w-[200px] h-[100px] mr-[12px] mb-[12px] cursor-pointer border bg-[#eee]">
|
||||
<img :src="img(item.url)" />
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="showTitleDialog = false">{{ t('cancel') }}</el-button>
|
||||
<el-button type="primary" @click="confirmTitleStyle">{{ t('confirm') }}</el-button>
|
||||
</span>
|
||||
</template>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="showTitleDialog = false">{{ t('cancel') }}</el-button>
|
||||
<el-button type="primary" @click="confirmTitleStyle">{{ t('confirm') }}</el-button>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
</el-dialog>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('activeCubeBlockContent') }}</h3>
|
||||
<el-form label-width="90px" class="px-[10px]">
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('activeCubeBlockContent') }}</h3>
|
||||
<el-form label-width="90px" class="px-[10px]">
|
||||
|
||||
<el-form-item :label="t('selectStyle')" class="flex">
|
||||
<span class="text-primary flex-1 cursor-pointer" @click="showBlockStyle">{{ diyStore.editComponent.blockStyle.title }}</span>
|
||||
<el-icon>
|
||||
<ArrowRight />
|
||||
</el-icon>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('selectStyle')" class="flex">
|
||||
<span class="text-primary flex-1 cursor-pointer"
|
||||
@click="showBlockStyle">{{ diyStore.editComponent.blockStyle.title }}</span>
|
||||
<el-icon>
|
||||
<ArrowRight />
|
||||
</el-icon>
|
||||
</el-form-item>
|
||||
|
||||
<el-dialog v-model="showListDialog" :title="t('selectStyle')" width="600px">
|
||||
<div class="flex flex-wrap">
|
||||
<template v-for="(item,index) in blockStyleList" :key="index">
|
||||
<div :class="{ 'border-primary': selectBlockStyle.value == item.value }" @click="changeBlockStyle(item)" class="flex items-center justify-center overflow-hidden w-[250px] h-[150px] mr-[12px] mb-[12px] cursor-pointer border bg-[#eee]">
|
||||
<img :src="img(item.url)" />
|
||||
</div>
|
||||
</template>
|
||||
<el-dialog v-model="showListDialog" :title="t('selectStyle')" width="600px">
|
||||
<div class="flex flex-wrap">
|
||||
<template v-for="(item,index) in blockStyleList" :key="index">
|
||||
<div :class="{ 'border-primary': selectBlockStyle.value == item.value }"
|
||||
@click="changeBlockStyle(item)"
|
||||
class="flex items-center justify-center overflow-hidden w-[250px] h-[150px] mr-[12px] mb-[12px] cursor-pointer border bg-[#eee]">
|
||||
<img :src="img(item.url)" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="showListDialog = false">{{ t('cancel') }}</el-button>
|
||||
<el-button type="primary" @click="confirmBlockStyle">{{ t('confirm') }}</el-button>
|
||||
</span>
|
||||
</template>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="showListDialog = false">{{ t('cancel') }}</el-button>
|
||||
<el-button type="primary" @click="confirmBlockStyle">{{ t('confirm') }}</el-button>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
</el-dialog>
|
||||
</el-dialog>
|
||||
|
||||
<p class="text-sm text-gray-400 mb-[10px]">{{ t('dragMouseAdjustOrder') }}</p>
|
||||
<p class="text-sm text-gray-400 mb-[10px]">{{ t('dragMouseAdjustOrder') }}</p>
|
||||
|
||||
<div ref="blockBoxRef">
|
||||
<div v-for="(item,index) in diyStore.editComponent.list" :key="item.id" class="item-wrap p-[10px] pb-0 relative border border-dashed border-gray-300 mb-[16px]">
|
||||
<el-form-item :label="t('image')">
|
||||
<upload-image v-model="item.imageUrl" :limit="1"/>
|
||||
</el-form-item>
|
||||
<div ref="blockBoxRef">
|
||||
<div v-for="(item,index) in diyStore.editComponent.list" :key="item.id"
|
||||
class="item-wrap p-[10px] pb-0 relative border border-dashed border-gray-300 mb-[16px]">
|
||||
<el-form-item :label="t('image')">
|
||||
<upload-image v-model="item.imageUrl" :limit="1" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('activeCubeTitle')">
|
||||
<el-input v-model.trim="item.title.text" :placeholder="t('activeCubeTitlePlaceholder')" clearable maxlength="4" show-word-limit/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('activeCubeTitle')">
|
||||
<el-input v-model.trim="item.title.text" :placeholder="t('activeCubeTitlePlaceholder')"
|
||||
clearable maxlength="4" show-word-limit />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('activeCubeSubTitleTextColor')" v-show="diyStore.editComponent.blockStyle.value == 'style-3'">
|
||||
<el-color-picker v-model="item.title.textColor" show-alpha :predefine="diyStore.predefineColors" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('activeCubeSubTitle')" v-if="diyStore.editComponent.blockStyle.value != 'style-3'">
|
||||
<el-input v-model.trim="item.subTitle.text" :placeholder="t('activeCubeSubTitlePlaceholder')" clearable maxlength="6" show-word-limit/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('activeCubeSubTitle')" v-if="diyStore.editComponent.blockStyle.value != 'style-3'">
|
||||
<el-input v-model.trim="item.subTitle.text" :placeholder="t('activeCubeSubTitlePlaceholder')" clearable maxlength="6" show-word-limit />
|
||||
</el-form-item>
|
||||
|
||||
<div v-show="diyStore.editComponent.blockStyle.value == 'style-4'">
|
||||
<el-form-item :label="t('activeCubeSubTitleTextColor')">
|
||||
@ -104,99 +111,105 @@
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('activeCubeSubTitleBgColor')">
|
||||
<el-color-picker v-model="item.subTitle.startColor" show-alpha :predefine="diyStore.predefineColors" />
|
||||
<icon name="iconfont iconmap-connect" size="20px" class="block !text-gray-400 mx-[5px]"/>
|
||||
<el-color-picker v-model="item.subTitle.endColor" show-alpha :predefine="diyStore.predefineColors"/>
|
||||
<icon name="iconfont iconmap-connect" size="20px" class="block !text-gray-400 mx-[5px]" />
|
||||
<el-color-picker v-model="item.subTitle.endColor" show-alpha :predefine="diyStore.predefineColors" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<el-form-item :label="t('activeListFrameColor')">
|
||||
<el-color-picker v-model="item.listFrame.startColor" show-alpha :predefine="diyStore.predefineColors" />
|
||||
<icon name="iconfont iconmap-connect" size="20px" class="block !text-gray-400 mx-[5px]"/>
|
||||
<el-color-picker v-model="item.listFrame.endColor" show-alpha :predefine="diyStore.predefineColors"/>
|
||||
<icon name="iconfont iconmap-connect" size="20px" class="block !text-gray-400 mx-[5px]" />
|
||||
<el-color-picker v-model="item.listFrame.endColor" show-alpha :predefine="diyStore.predefineColors" />
|
||||
</el-form-item>
|
||||
|
||||
<div v-show="diyStore.editComponent.blockStyle.value != 'style-4' && diyStore.editComponent.blockStyle.value != 'style-3'">
|
||||
<div
|
||||
v-show="diyStore.editComponent.blockStyle.value != 'style-4' && diyStore.editComponent.blockStyle.value != 'style-3'">
|
||||
<el-form-item :label="t('activeCubeButton')">
|
||||
<el-input v-model.trim="item.moreTitle.text" :placeholder="t('activeCubeButtonPlaceholder')" clearable maxlength="3" show-word-limit/>
|
||||
<el-input v-model.trim="item.moreTitle.text" :placeholder="t('activeCubeButtonPlaceholder')" clearable maxlength="3" show-word-limit />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('activeCubeButtonColor')">
|
||||
<el-color-picker v-model="item.moreTitle.startColor" show-alpha :predefine="diyStore.predefineColors" />
|
||||
<icon name="iconfont iconmap-connect" size="20px" class="block !text-gray-400 mx-[5px]"/>
|
||||
<el-color-picker v-model="item.moreTitle.endColor" show-alpha :predefine="diyStore.predefineColors"/>
|
||||
<icon name="iconfont iconmap-connect" size="20px" class="block !text-gray-400 mx-[5px]" />
|
||||
<el-color-picker v-model="item.moreTitle.endColor" show-alpha :predefine="diyStore.predefineColors" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<el-form-item :label="t('link')">
|
||||
<diy-link v-model="item.link"/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('link')">
|
||||
<diy-link v-model="item.link" />
|
||||
</el-form-item>
|
||||
|
||||
<div class="del absolute cursor-pointer z-[2] top-[-8px] right-[-8px]" v-show="diyStore.editComponent.list.length > 1" @click="diyStore.editComponent.list.splice(index,1)">
|
||||
<icon name="element CircleCloseFilled" color="#bbb" size="20px"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="del absolute cursor-pointer z-[2] top-[-8px] right-[-8px]"
|
||||
v-show="diyStore.editComponent.list.length > 1"
|
||||
@click="diyStore.editComponent.list.splice(index,1)">
|
||||
<icon name="element CircleCloseFilled" color="#bbb" size="20px" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-button v-show="diyStore.editComponent.list.length < 10" class="w-full" @click="addItem">{{ t('activeCubeAddItem') }}</el-button>
|
||||
<el-button v-show="diyStore.editComponent.list.length < 10" class="w-full" @click="addItem">
|
||||
{{ t('activeCubeAddItem') }}
|
||||
</el-button>
|
||||
|
||||
</el-form>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
|
||||
<div class="edit-attr-item-wrap" v-if="selectTitleStyle.value != 'style-5'">
|
||||
<h3 class="mb-[10px]">{{ t('titleStyle') }}</h3>
|
||||
<el-form label-width="90px" class="px-[10px]">
|
||||
<el-form-item :label="t('textColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.titleColor" show-alpha :predefine="diyStore.predefineColors"/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="edit-attr-item-wrap" v-if="selectTitleStyle.value != 'style-5'">
|
||||
<h3 class="mb-[10px]">{{ t('titleStyle') }}</h3>
|
||||
<el-form label-width="90px" class="px-[10px]">
|
||||
<el-form-item :label="t('textColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.titleColor" show-alpha :predefine="diyStore.predefineColors" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('subTitleStyle') }}</h3>
|
||||
<el-form label-width="90px" class="px-[10px]">
|
||||
<el-form-item :label="t('textColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.subTitle.textColor" show-alpha :predefine="diyStore.predefineColors"/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('subTextBgColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.subTitle.startColor" show-alpha :predefine="diyStore.predefineColors"/>
|
||||
<icon name="iconfont iconmap-connect" size="20px" class="block !text-gray-400 mx-[5px]"/>
|
||||
<el-color-picker v-model="diyStore.editComponent.subTitle.endColor" show-alpha :predefine="diyStore.predefineColors"/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('subTitleStyle') }}</h3>
|
||||
<el-form label-width="90px" class="px-[10px]">
|
||||
<el-form-item :label="t('textColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.subTitle.textColor" show-alpha
|
||||
:predefine="diyStore.predefineColors" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('subTextBgColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.subTitle.startColor" show-alpha :predefine="diyStore.predefineColors" />
|
||||
<icon name="iconfont iconmap-connect" size="20px" class="block !text-gray-400 mx-[5px]" />
|
||||
<el-color-picker v-model="diyStore.editComponent.subTitle.endColor" show-alpha :predefine="diyStore.predefineColors" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('activeCubeBlockStyle') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('activeCubeBlockTextFontWeight')">
|
||||
<el-radio-group v-model="diyStore.editComponent.blockStyle.fontWeight">
|
||||
<el-radio :label="'normal'">{{t('fontWeightNormal')}}</el-radio>
|
||||
<el-radio :label="'bold'">{{t('fontWeightBold')}}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('activeCubeBlockStyle') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('activeCubeBlockTextFontWeight')">
|
||||
<el-radio-group v-model="diyStore.editComponent.blockStyle.fontWeight">
|
||||
<el-radio :label="'normal'">{{ t('fontWeightNormal') }}</el-radio>
|
||||
<el-radio :label="'bold'">{{ t('fontWeightBold') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('activeCubeBlockBtnText')" class="flex">
|
||||
<el-radio-group v-model="diyStore.editComponent.blockStyle.btnText">
|
||||
<el-radio :label="'normal'">{{t('btnTextNormal')}}</el-radio>
|
||||
<el-radio :label="'italics'">{{t('btnTextItalics')}}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('topRounded')">
|
||||
<el-slider v-model="diyStore.editComponent.topElementRounded" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('bottomRounded')">
|
||||
<el-slider v-model="diyStore.editComponent.bottomElementRounded" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<el-radio-group v-model="diyStore.editComponent.blockStyle.btnText">
|
||||
<el-radio :label="'normal'">{{ t('btnTextNormal') }}</el-radio>
|
||||
<el-radio :label="'italics'">{{ t('btnTextItalics') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('topRounded')">
|
||||
<el-slider v-model="diyStore.editComponent.topElementRounded" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('bottomRounded')">
|
||||
<el-slider v-model="diyStore.editComponent.bottomElementRounded" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
</div>
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
@ -215,7 +228,7 @@ diyStore.editComponent.ignore = [] // 忽略公共属性
|
||||
diyStore.editComponent.verify = (index: number) => {
|
||||
const res = { code: true, message: '' }
|
||||
|
||||
if(diyStore.value[index].text == ''){
|
||||
if (diyStore.value[index].text == '') {
|
||||
res.code = false
|
||||
res.message = t('activeCubeTitlePlaceholder')
|
||||
return res
|
||||
@ -232,14 +245,14 @@ diyStore.editComponent.verify = (index: number) => {
|
||||
res.message = t('activeCubeTitlePlaceholder')
|
||||
return res
|
||||
}
|
||||
if(['style-1','style-2','style-4'].indexOf(diyStore.value[index].blockStyle.value) != -1){
|
||||
if (['style-1', 'style-2', 'style-4'].indexOf(diyStore.value[index].blockStyle.value) != -1) {
|
||||
if (item.subTitle.text === '') {
|
||||
res.code = false
|
||||
res.message = t('activeCubeSubTitlePlaceholder')
|
||||
return res
|
||||
}
|
||||
}
|
||||
if(['style-1','style-2'].indexOf(diyStore.value[index].blockStyle.value) != -1){
|
||||
if (['style-1', 'style-2'].indexOf(diyStore.value[index].blockStyle.value) != -1) {
|
||||
if (item.moreTitle.text === '') {
|
||||
res.code = false
|
||||
res.message = t('activeCubeButtonPlaceholder')
|
||||
@ -258,33 +271,33 @@ diyStore.editComponent.list.forEach((item: any) => {
|
||||
const showTitleDialog = ref(false)
|
||||
|
||||
const showTitleStyle = () => {
|
||||
selectTitleStyle.title = diyStore.editComponent.titleStyle.title;
|
||||
selectTitleStyle.value = diyStore.editComponent.titleStyle.value;
|
||||
selectTitleStyle.title = diyStore.editComponent.titleStyle.title;
|
||||
selectTitleStyle.value = diyStore.editComponent.titleStyle.value;
|
||||
showTitleDialog.value = true
|
||||
}
|
||||
|
||||
const titleStyleList = reactive([
|
||||
{
|
||||
url : 'static/resource/images/diy/active_cube/title_style1.png',
|
||||
title:'风格1',
|
||||
value:'style-1'
|
||||
},{
|
||||
url : 'static/resource/images/diy/active_cube/title_style2.png',
|
||||
title:'风格2',
|
||||
value:'style-2'
|
||||
},{
|
||||
url : 'static/resource/images/diy/active_cube/title_style3.png',
|
||||
title:'风格3',
|
||||
value:'style-3'
|
||||
},{
|
||||
url : 'static/resource/images/diy/active_cube/title_style5.png',
|
||||
title:'风格4',
|
||||
value:'style-4'
|
||||
},{
|
||||
url : 'static/resource/images/diy/active_cube/title_style6.png',
|
||||
title:'风格5',
|
||||
value:'style-5'
|
||||
}
|
||||
{
|
||||
url: 'static/resource/images/diy/active_cube/title_style1.png',
|
||||
title: '风格1',
|
||||
value: 'style-1'
|
||||
}, {
|
||||
url: 'static/resource/images/diy/active_cube/title_style2.png',
|
||||
title: '风格2',
|
||||
value: 'style-2'
|
||||
}, {
|
||||
url: 'static/resource/images/diy/active_cube/title_style3.png',
|
||||
title: '风格3',
|
||||
value: 'style-3'
|
||||
}, {
|
||||
url: 'static/resource/images/diy/active_cube/title_style5.png',
|
||||
title: '风格4',
|
||||
value: 'style-4'
|
||||
}, {
|
||||
url: 'static/resource/images/diy/active_cube/title_style6.png',
|
||||
title: '风格5',
|
||||
value: 'style-5'
|
||||
}
|
||||
])
|
||||
|
||||
const selectTitleStyle = reactive({
|
||||
@ -292,7 +305,7 @@ const selectTitleStyle = reactive({
|
||||
value: diyStore.editComponent.titleStyle.value
|
||||
})
|
||||
|
||||
const changeTitleStyle = (item:any) => {
|
||||
const changeTitleStyle = (item: any) => {
|
||||
selectTitleStyle.title = item.title;
|
||||
selectTitleStyle.value = item.value;
|
||||
}
|
||||
@ -304,28 +317,28 @@ const confirmTitleStyle = () => {
|
||||
showTitleDialog.value = false
|
||||
}
|
||||
|
||||
const initTitleStyle = (style)=>{
|
||||
if(diyStore.editComponent.titleStyle.value == 'style-1'){
|
||||
const initTitleStyle = (style) => {
|
||||
if (diyStore.editComponent.titleStyle.value == 'style-1') {
|
||||
diyStore.editComponent.titleColor = "#F91700";
|
||||
diyStore.editComponent.subTitle.textColor = "#FFFFFF";
|
||||
diyStore.editComponent.subTitle.startColor = "#FB792F";
|
||||
diyStore.editComponent.subTitle.endColor = "#F91700";
|
||||
}else if(diyStore.editComponent.titleStyle.value == 'style-2'){
|
||||
} else if (diyStore.editComponent.titleStyle.value == 'style-2') {
|
||||
diyStore.editComponent.titleColor = "#F91700";
|
||||
diyStore.editComponent.subTitle.textColor = "#FFFFFF";
|
||||
diyStore.editComponent.subTitle.startColor = "#FB792F";
|
||||
diyStore.editComponent.subTitle.endColor = "#F91700";
|
||||
}else if(diyStore.editComponent.titleStyle.value == 'style-3'){
|
||||
} else if (diyStore.editComponent.titleStyle.value == 'style-3') {
|
||||
diyStore.editComponent.titleColor = "#F91700";
|
||||
diyStore.editComponent.subTitle.textColor = "#FFFFFF";
|
||||
diyStore.editComponent.subTitle.startColor = "#FB792F";
|
||||
diyStore.editComponent.subTitle.endColor = "#F91700";
|
||||
}else if(diyStore.editComponent.titleStyle.value == 'style-4'){
|
||||
} else if (diyStore.editComponent.titleStyle.value == 'style-4') {
|
||||
diyStore.editComponent.titleColor = "#FFFFFF";
|
||||
diyStore.editComponent.subTitle.textColor = "#333333";
|
||||
diyStore.editComponent.subTitle.startColor = "#FFFFFF";
|
||||
diyStore.editComponent.subTitle.endColor = "#FFFFFF";
|
||||
}else if(diyStore.editComponent.titleStyle.value == 'style-5'){
|
||||
} else if (diyStore.editComponent.titleStyle.value == 'style-5') {
|
||||
diyStore.editComponent.titleColor = "";
|
||||
diyStore.editComponent.subTitle.textColor = "#999999";
|
||||
diyStore.editComponent.subTitle.startColor = "#FFFFFF";
|
||||
@ -342,24 +355,24 @@ const showBlockStyle = () => {
|
||||
|
||||
const blockStyleList = reactive([
|
||||
{
|
||||
url : 'static/resource/images/diy/active_cube/block_style1.png',
|
||||
title:'风格1',
|
||||
value:'style-1'
|
||||
url: 'static/resource/images/diy/active_cube/block_style1.png',
|
||||
title: '风格1',
|
||||
value: 'style-1'
|
||||
},
|
||||
{
|
||||
url : 'static/resource/images/diy/active_cube/block_style2.png',
|
||||
title:'风格2',
|
||||
value:'style-2'
|
||||
url: 'static/resource/images/diy/active_cube/block_style2.png',
|
||||
title: '风格2',
|
||||
value: 'style-2'
|
||||
},
|
||||
{
|
||||
url : 'static/resource/images/diy/active_cube/block_style3.png',
|
||||
title:'风格3',
|
||||
value:'style-3'
|
||||
url: 'static/resource/images/diy/active_cube/block_style3.png',
|
||||
title: '风格3',
|
||||
value: 'style-3'
|
||||
},
|
||||
{
|
||||
url : 'static/resource/images/diy/active_cube/block_style4.png',
|
||||
title:'风格4',
|
||||
value:'style-4'
|
||||
url: 'static/resource/images/diy/active_cube/block_style4.png',
|
||||
title: '风格4',
|
||||
value: 'style-4'
|
||||
}
|
||||
])
|
||||
|
||||
@ -368,7 +381,7 @@ const selectBlockStyle = reactive({
|
||||
value: diyStore.editComponent.blockStyle.value
|
||||
})
|
||||
|
||||
const changeBlockStyle = (item:any) => {
|
||||
const changeBlockStyle = (item: any) => {
|
||||
selectBlockStyle.title = item.title;
|
||||
selectBlockStyle.value = item.value;
|
||||
}
|
||||
@ -380,8 +393,8 @@ const confirmBlockStyle = () => {
|
||||
showListDialog.value = false
|
||||
}
|
||||
|
||||
const initBlockStyle = (style: any)=>{
|
||||
if(style == 'style-1'){
|
||||
const initBlockStyle = (style: any) => {
|
||||
if (style == 'style-1') {
|
||||
diyStore.editComponent.blockStyle.fontWeight = "normal";
|
||||
diyStore.editComponent.blockStyle.btnText = "normal";
|
||||
|
||||
@ -421,7 +434,7 @@ const initBlockStyle = (style: any)=>{
|
||||
diyStore.editComponent.list[3].listFrame.startColor = "#FFFAF5";
|
||||
diyStore.editComponent.list[3].listFrame.endColor = "#FFFFFF";
|
||||
|
||||
}else if(style == 'style-2'){
|
||||
} else if (style == 'style-2') {
|
||||
diyStore.editComponent.blockStyle.fontWeight = "normal";
|
||||
diyStore.editComponent.blockStyle.btnText = "normal";
|
||||
|
||||
@ -463,7 +476,7 @@ const initBlockStyle = (style: any)=>{
|
||||
diyStore.editComponent.list[3].moreTitle.endColor = "#F91700";
|
||||
diyStore.editComponent.list[3].listFrame.startColor = "#FFEAEA";
|
||||
diyStore.editComponent.list[3].listFrame.endColor = "#FFFCFB";
|
||||
}else if(style == 'style-3'){
|
||||
} else if (style == 'style-3') {
|
||||
diyStore.editComponent.blockStyle.fontWeight = "normal";
|
||||
diyStore.editComponent.blockStyle.btnText = "normal";
|
||||
|
||||
@ -502,7 +515,7 @@ const initBlockStyle = (style: any)=>{
|
||||
diyStore.editComponent.list[3].moreTitle.endColor = "";
|
||||
diyStore.editComponent.list[3].listFrame.startColor = "";
|
||||
diyStore.editComponent.list[3].listFrame.endColor = "";
|
||||
}else if(style == 'style-4'){
|
||||
} else if (style == 'style-4') {
|
||||
diyStore.editComponent.blockStyle.fontWeight = "bold";
|
||||
diyStore.editComponent.blockStyle.btnText = "normal";
|
||||
|
||||
@ -547,24 +560,24 @@ const initBlockStyle = (style: any)=>{
|
||||
const addItem = () => {
|
||||
diyStore.editComponent.list.push({
|
||||
id: diyStore.generateRandom(),
|
||||
title:{
|
||||
title:'标题',
|
||||
title: {
|
||||
title: '标题',
|
||||
textColor: "#000000"
|
||||
},
|
||||
subTitle:{
|
||||
text:'副标题',
|
||||
subTitle: {
|
||||
text: '副标题',
|
||||
textColor: "#999999",
|
||||
startColor:'',
|
||||
endColor:''
|
||||
startColor: '',
|
||||
endColor: ''
|
||||
},
|
||||
listFrame: {
|
||||
startColor: "#4AC1FF",
|
||||
endColor: "#1D7CFF"
|
||||
},
|
||||
moreTitle:{
|
||||
text:'去看看',
|
||||
startColor:'#FEA715',
|
||||
endColor:'#FE1E00'
|
||||
moreTitle: {
|
||||
text: '去看看',
|
||||
startColor: '#FEA715',
|
||||
endColor: '#FE1E00'
|
||||
},
|
||||
imageUrl: '',
|
||||
link: { name: '' }
|
||||
|
||||
@ -1,105 +1,106 @@
|
||||
<template>
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('carouselSearchShowPosition') }}</h3>
|
||||
<el-form label-width="100px" class="px-[10px]">
|
||||
<el-form-item :label="t('carouselSearchShowWay')">
|
||||
<el-radio-group v-model="diyStore.editComponent.positionWay">
|
||||
<el-radio label="static">{{ t('carouselSearchShowWayStatic') }}</el-radio>
|
||||
<el-radio label="fixed">{{ t('carouselSearchShowWayFixed') }}</el-radio>
|
||||
</el-radio-group>
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('carouselSearchShowPosition') }}</h3>
|
||||
<el-form label-width="100px" class="px-[10px]">
|
||||
<el-form-item :label="t('carouselSearchShowWay')">
|
||||
<el-radio-group v-model="diyStore.editComponent.positionWay">
|
||||
<el-radio label="static">{{ t('carouselSearchShowWayStatic') }}</el-radio>
|
||||
<el-radio label="fixed">{{ t('carouselSearchShowWayFixed') }}</el-radio>
|
||||
</el-radio-group>
|
||||
<div v-if="diyStore.editComponent.positionWay == 'fixed'" class="text-sm text-gray-400 mb-[10px]">滑动页面查看效果</div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('carouselSearchFixedBgColor')" v-show="diyStore.editComponent.positionWay == 'fixed'">
|
||||
<el-color-picker v-model="diyStore.editComponent.fixedBgColor" show-alpha :predefine="diyStore.predefineColors"/>
|
||||
</el-form-item>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('carouselSearchFixedBgColor')" v-show="diyStore.editComponent.positionWay == 'fixed'">
|
||||
<el-color-picker v-model="diyStore.editComponent.fixedBgColor" show-alpha :predefine="diyStore.predefineColors" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('carouselSearchBgGradient')">
|
||||
<el-radio-group v-model="diyStore.editComponent.bgGradient">
|
||||
<el-radio :label="true">{{ t('carouselSearchOpen') }}</el-radio>
|
||||
<el-radio :label="false">{{ t('carouselSearchClose') }}</el-radio>
|
||||
</el-radio-group>
|
||||
<el-radio :label="true">{{ t('carouselSearchOpen') }}</el-radio>
|
||||
<el-radio :label="false">{{ t('carouselSearchClose') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('carouselSearchSet') }}</h3>
|
||||
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
|
||||
<el-form-item :label="t('selectStyle')" class="flex">
|
||||
<span class="text-primary flex-1 cursor-pointer" @click="showSearchStyle">{{ diyStore.editComponent.search.styleName }}</span>
|
||||
<el-icon>
|
||||
<ArrowRight />
|
||||
</el-icon>
|
||||
</el-form-item>
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('carouselSearchSet') }}</h3>
|
||||
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
|
||||
<el-form-item :label="t('selectStyle')" class="flex">
|
||||
<span class="text-primary flex-1 cursor-pointer" @click="showSearchStyle">{{ diyStore.editComponent.search.styleName }}</span>
|
||||
<el-icon>
|
||||
<ArrowRight />
|
||||
</el-icon>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('carouselSearchSubTitle')" v-if="diyStore.editComponent.search.style == 'style-2'">
|
||||
<el-input v-model.trim="diyStore.editComponent.search.subTitle.text" :placeholder="t('carouselSearchSubTitlePlaceholder')" clearable maxlength="10" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('logo')">
|
||||
<upload-image v-model="diyStore.editComponent.search.logo" :limit="1" />
|
||||
<div class="text-sm text-gray-400 mb-[10px]">{{ t('carouselSearchLogoTips') }}</div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('carouselSearchText')">
|
||||
<div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('logo')">
|
||||
<upload-image v-model="diyStore.editComponent.search.logo" :limit="1" />
|
||||
<div class="text-sm text-gray-400 mb-[10px]">{{ t('carouselSearchLogoTips') }}</div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('carouselSearchText')">
|
||||
<div>
|
||||
<el-input v-model.trim="diyStore.editComponent.search.text" :placeholder="t('carouselSearchPlaceholder')" clearable maxlength="20" show-word-limit />
|
||||
<p class="text-sm text-gray-400 mt-[10px] leading-[1.5]">{{t('carouselSearchTextTips')}}</p>
|
||||
<p class="text-sm text-gray-400 mt-[10px] leading-[1.5]">{{ t('carouselSearchTextTips') }}</p>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('link')">
|
||||
<diy-link v-model="diyStore.editComponent.search.link"/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('link')">
|
||||
<diy-link v-model="diyStore.editComponent.search.link" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-dialog v-model="showSearchDialog" :title="t('selectStyle')" width="500px">
|
||||
|
||||
<div class="flex flex-wrap">
|
||||
<template v-for="(item,index) in searchStyleList" :key="index">
|
||||
<div :class="{ 'border-primary': selectSearchStyle.value == item.value }" @click="changeSearchStyle(item)" class="flex items-center justify-center overflow-hidden w-[200px] h-[100px] m-[6px] cursor-pointer border bg-[#eee]">
|
||||
<img :src="img(item.url)" />
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class="flex flex-wrap">
|
||||
<template v-for="(item,index) in searchStyleList" :key="index">
|
||||
<div :class="{ 'border-primary': selectSearchStyle.value == item.value }" @click="changeSearchStyle(item)" class="flex items-center justify-center overflow-hidden w-[200px] h-[100px] m-[6px] cursor-pointer border bg-[#eee]">
|
||||
<img :src="img(item.url)" />
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="showSearchDialog = false">{{ t('cancel') }}</el-button>
|
||||
<el-button type="primary" @click="confirmSearchStyle">{{ t('confirm') }}</el-button>
|
||||
</span>
|
||||
</template>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="showSearchDialog = false">{{ t('cancel') }}</el-button>
|
||||
<el-button type="primary" @click="confirmSearchStyle">{{ t('confirm') }}</el-button>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
</el-dialog>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
|
||||
<div class="edit-attr-item-wrap mb-[20px]">
|
||||
<h3 class="mb-[10px]">{{ t('carouselSearchHotWordSet') }}</h3>
|
||||
<el-form label-width="100px" class="px-[10px]">
|
||||
<div class="edit-attr-item-wrap mb-[20px]">
|
||||
<h3 class="mb-[10px]">{{ t('carouselSearchHotWordSet') }}</h3>
|
||||
<el-form label-width="100px" class="px-[10px]">
|
||||
|
||||
<el-form-item :label="t('carouselSearchHotWordInterval')">
|
||||
<el-slider v-model="diyStore.editComponent.search.hotWord.interval" show-input size="small" class="ml-[10px] diy-nav-slider" :min="1" :max="10"/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('carouselSearchHotWordInterval')">
|
||||
<el-slider v-model="diyStore.editComponent.search.hotWord.interval" show-input size="small" class="ml-[10px] diy-nav-slider" :min="1" :max="10" />
|
||||
</el-form-item>
|
||||
|
||||
<p class="text-sm text-gray-400 mb-[10px]">{{ t('dragMouseAdjustOrder') }}</p>
|
||||
<p class="text-sm text-gray-400 mb-[10px]">{{ t('dragMouseAdjustOrder') }}</p>
|
||||
|
||||
<div ref="searchHotWordTabBoxRef">
|
||||
<div v-for="(item,index) in diyStore.editComponent.search.hotWord.list" :key="item.id" class="item-wrap p-[10px] relative border border-dashed border-gray-300 mb-[16px]">
|
||||
<div ref="searchHotWordTabBoxRef">
|
||||
<div v-for="(item,index) in diyStore.editComponent.search.hotWord.list" :key="item.id"
|
||||
class="item-wrap p-[10px] relative border border-dashed border-gray-300 mb-[16px]">
|
||||
|
||||
<el-form-item :label="t('carouselSearchHotWordText')" class="!mb-0">
|
||||
<el-input v-model.trim="item.text" :placeholder="t('carouselSearchHotWordTextPlaceholder')" clearable maxlength="4" show-word-limit/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('carouselSearchHotWordText')" class="!mb-0">
|
||||
<el-input v-model.trim="item.text" :placeholder="t('carouselSearchHotWordTextPlaceholder')" clearable maxlength="4" show-word-limit />
|
||||
</el-form-item>
|
||||
|
||||
<div class="del absolute cursor-pointer z-[2] top-[-8px] right-[-8px]" @click="diyStore.editComponent.search.hotWord.list.splice(index,1)">
|
||||
<icon name="element CircleCloseFilled" color="#bbb" size="20px"/>
|
||||
</div>
|
||||
<div class="del absolute cursor-pointer z-[2] top-[-8px] right-[-8px]" @click="diyStore.editComponent.search.hotWord.list.splice(index,1)">
|
||||
<icon name="element CircleCloseFilled" color="#bbb" size="20px" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<el-button v-show="diyStore.editComponent.search.hotWord.list.length < 50" class="w-full" @click="addHotWordItem">{{ t('carouselSearchAddHotWordItem') }}</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<el-button v-show="diyStore.editComponent.search.hotWord.list.length < 50" class="w-full" @click="addHotWordItem">{{ t('carouselSearchAddHotWordItem') }}</el-button>
|
||||
</div>
|
||||
|
||||
</el-form>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<el-collapse v-model="activeNames" @change="handleChange" class="collapse-wrap">
|
||||
<el-collapse v-model="activeNames" @change="handleChange" class="collapse-wrap">
|
||||
<el-collapse-item :title="t('carouselSearchTabSet')" name="tab">
|
||||
<div class="edit-attr-item-wrap">
|
||||
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
|
||||
@ -113,7 +114,7 @@
|
||||
<div v-for="(item,index) in diyStore.editComponent.tab.list" :key="item.id" class="item-wrap p-[10px] pb-0 relative border border-dashed border-gray-300 mb-[16px]">
|
||||
|
||||
<el-form-item :label="t('carouselSearchTabCategoryText')">
|
||||
<el-input v-model.trim="item.text" :placeholder="t('carouselSearchTabCategoryTextPlaceholder')" clearable maxlength="4" show-word-limit/>
|
||||
<el-input v-model.trim="item.text" :placeholder="t('carouselSearchTabCategoryTextPlaceholder')" clearable maxlength="4" show-word-limit />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('dataSources')">
|
||||
@ -131,8 +132,10 @@
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
|
||||
<div class="del absolute cursor-pointer z-[2] top-[-8px] right-[-8px]" v-show="diyStore.editComponent.tab.list.length > 1" @click="diyStore.editComponent.tab.list.splice(index,1)">
|
||||
<icon name="element CircleCloseFilled" color="#bbb" size="20px"/>
|
||||
<div class="del absolute cursor-pointer z-[2] top-[-8px] right-[-8px]"
|
||||
v-show="diyStore.editComponent.tab.list.length > 1"
|
||||
@click="diyStore.editComponent.tab.list.splice(index,1)">
|
||||
<icon name="element CircleCloseFilled" color="#bbb" size="20px" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@ -141,7 +144,9 @@
|
||||
|
||||
<!-- 选择微页面弹出框 -->
|
||||
<el-dialog v-model="diyPageShowDialog" :title="t('selectSourcesDiyPage')" width="1000px" :close-on-press-escape="true" :destroy-on-close="true" :close-on-click-modal="false">
|
||||
<el-table :data="diyPageTable.data" ref="diyPageTableRef" size="large" v-loading="diyPageTable.loading" height="490px" @current-change="handleCurrentDiyPageChange" row-key="id" highlight-current-row>
|
||||
<el-table :data="diyPageTable.data" ref="diyPageTableRef" size="large"
|
||||
v-loading="diyPageTable.loading" height="490px"
|
||||
@current-change="handleCurrentDiyPageChange" row-key="id" highlight-current-row>
|
||||
<template #empty>
|
||||
<span>{{ !diyPageTable.loading ? t('emptyData') : '' }}</span>
|
||||
</template>
|
||||
@ -150,9 +155,11 @@
|
||||
<el-table-column prop="type_name" :label="t('diyPageForAddon')" min-width="80" />
|
||||
</el-table>
|
||||
<div class="mt-[16px] flex justify-end">
|
||||
<el-pagination v-model:current-page="diyPageTable.page" v-model:page-size="diyPageTable.limit"
|
||||
layout="total, sizes, prev, pager, next, jumper" :total="diyPageTable.total"
|
||||
@size-change="loadDiyPageList" @current-change="loadDiyPageList" />
|
||||
<el-pagination v-model:current-page="diyPageTable.page"
|
||||
v-model:page-size="diyPageTable.limit"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="diyPageTable.total"
|
||||
@size-change="loadDiyPageList" @current-change="loadDiyPageList" />
|
||||
</div>
|
||||
<div class="flex items-center justify-end mt-[15px]">
|
||||
<el-button type="primary" @click="saveDiyPageId">{{ t('confirm') }}</el-button>
|
||||
@ -169,144 +176,151 @@
|
||||
<el-switch v-model="diyStore.editComponent.swiper.control" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('carouselSearchSwiperInterval')">
|
||||
<el-slider v-model="diyStore.editComponent.swiper.interval" show-input size="small" class="ml-[10px] diy-nav-slider" :min="1" :max="10"/>
|
||||
<el-slider v-model="diyStore.editComponent.swiper.interval" show-input size="small" class="ml-[10px] diy-nav-slider" :min="1" :max="10" />
|
||||
</el-form-item>
|
||||
|
||||
<div class="text-sm text-gray-400 mb-[10px]">{{ t('carouselSearchSwiperTips') }}</div>
|
||||
|
||||
<div ref="imageBoxRef">
|
||||
<div v-for="(item,index) in diyStore.editComponent.swiper.list" :key="item.id" class="item-wrap p-[10px] pb-0 relative border border-dashed border-gray-300 mb-[16px]">
|
||||
<div v-for="(item,index) in diyStore.editComponent.swiper.list" :key="item.id"
|
||||
class="item-wrap p-[10px] pb-0 relative border border-dashed border-gray-300 mb-[16px]">
|
||||
<el-form-item :label="t('image')">
|
||||
<upload-image v-model="item.imageUrl" :limit="1" @change="selectImg" />
|
||||
</el-form-item>
|
||||
|
||||
<div class="del absolute cursor-pointer z-[2] top-[-8px] right-[-8px]" v-show="diyStore.editComponent.swiper.list.length > 1" @click="diyStore.editComponent.swiper.list.splice(index,1)">
|
||||
<icon name="element CircleCloseFilled" color="#bbb" size="20px"/>
|
||||
<div class="del absolute cursor-pointer z-[2] top-[-8px] right-[-8px]"
|
||||
v-show="diyStore.editComponent.swiper.list.length > 1"
|
||||
@click="diyStore.editComponent.swiper.list.splice(index,1)">
|
||||
<icon name="element CircleCloseFilled" color="#bbb" size="20px" />
|
||||
</div>
|
||||
|
||||
<el-form-item :label="t('link')">
|
||||
<diy-link v-model="item.link"/>
|
||||
<diy-link v-model="item.link" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-button v-show="diyStore.editComponent.swiper.list.length < 10" class="w-full" @click="addImageAd">{{ t('addImageAd') }}</el-button>
|
||||
<el-button v-show="diyStore.editComponent.swiper.list.length < 10" class="w-full"
|
||||
@click="addImageAd">{{ t('addImageAd') }}
|
||||
</el-button>
|
||||
|
||||
</el-form>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
<div class="edit-attr-item-wrap" v-if="diyStore.editComponent.search.style == 'style-2'">
|
||||
<h3 class="mb-[10px]">{{ t('carouselSearchPositionStyle') }}</h3>
|
||||
<el-form label-width="100px" class="px-[10px]">
|
||||
<el-form-item :label="t('carouselSearchTextColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.search.positionColor" show-alpha :predefine="diyStore.predefineColors"/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<h3 class="mb-[10px]">{{ t('carouselSearchPositionStyle') }}</h3>
|
||||
<el-form label-width="100px" class="px-[10px]">
|
||||
<el-form-item :label="t('carouselSearchTextColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.search.positionColor" show-alpha :predefine="diyStore.predefineColors" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<div class="edit-attr-item-wrap" v-if="diyStore.editComponent.search.style == 'style-2'">
|
||||
<h3 class="mb-[10px]">{{ t('carouselSearchSubTitleStyle') }}</h3>
|
||||
<el-form label-width="100px" class="px-[10px]">
|
||||
<el-form-item :label="t('carouselSearchTextColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.search.subTitle.textColor" show-alpha :predefine="diyStore.predefineColors"/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('carouselSearchBgColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.search.subTitle.startColor" :predefine="diyStore.predefineColors" show-alpha/>
|
||||
<icon name="iconfont iconmap-connect" size="20px" class="block !text-gray-400 mx-[5px]"/>
|
||||
<el-color-picker v-model="diyStore.editComponent.search.subTitle.endColor" :predefine="diyStore.predefineColors" show-alpha/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<h3 class="mb-[10px]">{{ t('carouselSearchSubTitleStyle') }}</h3>
|
||||
<el-form label-width="100px" class="px-[10px]">
|
||||
<el-form-item :label="t('carouselSearchTextColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.search.subTitle.textColor" show-alpha :predefine="diyStore.predefineColors" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('carouselSearchBgColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.search.subTitle.startColor" :predefine="diyStore.predefineColors" show-alpha />
|
||||
<icon name="iconfont iconmap-connect" size="20px" class="block !text-gray-400 mx-[5px]" />
|
||||
<el-color-picker v-model="diyStore.editComponent.search.subTitle.endColor" :predefine="diyStore.predefineColors" show-alpha />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('carouselSearchStyle') }}</h3>
|
||||
<el-form label-width="100px" class="px-[10px]">
|
||||
<el-form-item :label="t('carouselSearchTextColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.search.color" show-alpha :predefine="diyStore.predefineColors"/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('carouselSearchBgColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.search.bgColor" show-alpha :predefine="diyStore.predefineColors"/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('carouselSearchBtnColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.search.btnColor" show-alpha :predefine="diyStore.predefineColors"/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('carouselSearchBtnBgColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.search.btnBgColor" show-alpha :predefine="diyStore.predefineColors"/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<h3 class="mb-[10px]">{{ t('carouselSearchStyle') }}</h3>
|
||||
<el-form label-width="100px" class="px-[10px]">
|
||||
<el-form-item :label="t('carouselSearchTextColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.search.color" show-alpha :predefine="diyStore.predefineColors" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('carouselSearchBgColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.search.bgColor" show-alpha :predefine="diyStore.predefineColors" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('carouselSearchBtnColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.search.btnColor" show-alpha :predefine="diyStore.predefineColors" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('carouselSearchBtnBgColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.search.btnBgColor" show-alpha :predefine="diyStore.predefineColors" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('carouselSearchTabStyle') }}</h3>
|
||||
<el-form label-width="100px" class="px-[10px]">
|
||||
<el-form-item :label="t('noColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.tab.noColor" show-alpha :predefine="diyStore.predefineColors"/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('selectColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.tab.selectColor" show-alpha :predefine="diyStore.predefineColors"/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('fixedNoColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.tab.fixedNoColor" show-alpha :predefine="diyStore.predefineColors"/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('fixedSelectColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.tab.fixedSelectColor" show-alpha :predefine="diyStore.predefineColors"/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('carouselSearchTabStyle') }}</h3>
|
||||
<el-form label-width="100px" class="px-[10px]">
|
||||
<el-form-item :label="t('noColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.tab.noColor" show-alpha :predefine="diyStore.predefineColors" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('selectColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.tab.selectColor" show-alpha :predefine="diyStore.predefineColors" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('fixedNoColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.tab.fixedNoColor" show-alpha :predefine="diyStore.predefineColors" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('fixedSelectColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.tab.fixedSelectColor" show-alpha :predefine="diyStore.predefineColors" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('carouselSearchSwiperSet') }}</h3>
|
||||
<el-form label-width="100px" class="px-[10px]">
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('carouselSearchSwiperSet') }}</h3>
|
||||
<el-form label-width="100px" class="px-[10px]">
|
||||
<el-form-item :label="t('carouselSearchSwiperStyle')" @change="changeSwiperStyle">
|
||||
<el-radio-group v-model="diyStore.editComponent.swiper.swiperStyle">
|
||||
<el-radio label="style-1">{{ t('carouselSearchSwiperIndicatorStyle1') }}</el-radio>
|
||||
<el-radio label="style-2">{{ t('carouselSearchSwiperIndicatorStyle2') }}</el-radio>
|
||||
<el-radio label="style-3">{{ t('carouselSearchSwiperIndicatorStyle3') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('topRounded')">
|
||||
<el-slider v-model="diyStore.editComponent.swiper.topRounded" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('bottomRounded')">
|
||||
<el-slider v-model="diyStore.editComponent.swiper.bottomRounded" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<el-radio-group v-model="diyStore.editComponent.swiper.swiperStyle">
|
||||
<el-radio label="style-1">{{ t('carouselSearchSwiperIndicatorStyle1') }}</el-radio>
|
||||
<el-radio label="style-2">{{ t('carouselSearchSwiperIndicatorStyle2') }}</el-radio>
|
||||
<el-radio label="style-3">{{ t('carouselSearchSwiperIndicatorStyle3') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('topRounded')">
|
||||
<el-slider v-model="diyStore.editComponent.swiper.topRounded" show-input size="small"
|
||||
class="ml-[10px] diy-nav-slider" :max="50" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('bottomRounded')">
|
||||
<el-slider v-model="diyStore.editComponent.swiper.bottomRounded" show-input size="small"
|
||||
class="ml-[10px] diy-nav-slider" :max="50" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('carouselSearchSwiperIndicatorSet') }}</h3>
|
||||
<el-form label-width="100px" class="px-[10px]">
|
||||
<el-form-item :label="t('carouselSearchSwiperIndicatorStyle')">
|
||||
<el-radio-group v-model="diyStore.editComponent.swiper.indicatorStyle">
|
||||
<el-radio label="style-1">{{ t('carouselSearchSwiperIndicatorStyle1') }}</el-radio>
|
||||
<el-radio label="style-2">{{ t('carouselSearchSwiperIndicatorStyle2') }}</el-radio>
|
||||
<el-radio label="style-3">{{ t('carouselSearchSwiperIndicatorStyle3') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('carouselSearchSwiperIndicatorAlign')">
|
||||
<el-radio-group v-model="diyStore.editComponent.swiper.indicatorAlign">
|
||||
<el-radio label="left">{{ t('alignLeft') }}</el-radio>
|
||||
<el-radio label="center">{{ t('alignCenter') }}</el-radio>
|
||||
<el-radio label="right">{{ t('alignRight') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('noColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.swiper.indicatorColor" show-alpha :predefine="diyStore.predefineColors"/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('selectColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.swiper.indicatorActiveColor" show-alpha :predefine="diyStore.predefineColors"/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('carouselSearchSwiperIndicatorSet') }}</h3>
|
||||
<el-form label-width="100px" class="px-[10px]">
|
||||
<el-form-item :label="t('carouselSearchSwiperIndicatorStyle')">
|
||||
<el-radio-group v-model="diyStore.editComponent.swiper.indicatorStyle">
|
||||
<el-radio label="style-1">{{ t('carouselSearchSwiperIndicatorStyle1') }}</el-radio>
|
||||
<el-radio label="style-2">{{ t('carouselSearchSwiperIndicatorStyle2') }}</el-radio>
|
||||
<el-radio label="style-3">{{ t('carouselSearchSwiperIndicatorStyle3') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('carouselSearchSwiperIndicatorAlign')">
|
||||
<el-radio-group v-model="diyStore.editComponent.swiper.indicatorAlign">
|
||||
<el-radio label="left">{{ t('alignLeft') }}</el-radio>
|
||||
<el-radio label="center">{{ t('alignCenter') }}</el-radio>
|
||||
<el-radio label="right">{{ t('alignRight') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('noColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.swiper.indicatorColor" show-alpha :predefine="diyStore.predefineColors" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('selectColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.swiper.indicatorActiveColor" show-alpha :predefine="diyStore.predefineColors" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<!-- 组件样式 -->
|
||||
<!-- <slot name="style"></slot> -->
|
||||
</div>
|
||||
<!-- 组件样式 -->
|
||||
<!-- <slot name="style"></slot> -->
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
@ -317,19 +331,19 @@ import useDiyStore from '@/stores/modules/diy'
|
||||
import { ref, reactive, watch, onMounted, nextTick } from 'vue'
|
||||
import { ElTable } from 'element-plus'
|
||||
import Sortable from 'sortablejs'
|
||||
import { range,cloneDeep } from 'lodash-es'
|
||||
import { range, cloneDeep } from 'lodash-es'
|
||||
|
||||
import { getDiyPageListByCarouselSearch } from '@/app/api/diy'
|
||||
|
||||
const diyStore = useDiyStore()
|
||||
diyStore.editComponent.ignore = ['componentBgColor','componentBgUrl','marginTop','marginBottom','topRounded','bottomRounded','pageBgColor','marginBoth'] // 忽略公共属性
|
||||
diyStore.editComponent.ignore = ['componentBgColor', 'componentBgUrl', 'marginTop', 'marginBottom', 'topRounded', 'bottomRounded', 'pageBgColor', 'marginBoth'] // 忽略公共属性
|
||||
|
||||
// 组件验证
|
||||
diyStore.editComponent.verify = (index: number) => {
|
||||
const res = { code: true, message: '' }
|
||||
|
||||
diyStore.value[index].search.hotWord.list.forEach((item: any) => {
|
||||
if(item.text == ''){
|
||||
if (item.text == '') {
|
||||
res.code = false
|
||||
res.message = t('carouselSearchHotWordTextPlaceholder')
|
||||
return res
|
||||
@ -337,7 +351,7 @@ diyStore.editComponent.verify = (index: number) => {
|
||||
});
|
||||
|
||||
diyStore.value[index].tab.list.forEach((item: any) => {
|
||||
if(item.text == ''){
|
||||
if (item.text == '') {
|
||||
res.code = false
|
||||
res.message = t('carouselSearchTabCategoryTextPlaceholder')
|
||||
return res
|
||||
@ -349,9 +363,9 @@ diyStore.editComponent.verify = (index: number) => {
|
||||
// }
|
||||
});
|
||||
|
||||
if(diyStore.value[index].swiper.control){
|
||||
if (diyStore.value[index].swiper.control) {
|
||||
diyStore.value[index].swiper.list.forEach((item: any) => {
|
||||
if(item.imageUrl == ''){
|
||||
if (item.imageUrl == '') {
|
||||
res.code = false
|
||||
res.message = t('imageUrlTip')
|
||||
return res
|
||||
@ -376,7 +390,7 @@ const showSearchStyle = () => {
|
||||
selectSearchStyle.value = diyStore.editComponent.search.style;
|
||||
}
|
||||
|
||||
const changeSearchStyle = (item:any) => {
|
||||
const changeSearchStyle = (item: any) => {
|
||||
selectSearchStyle.title = item.title;
|
||||
selectSearchStyle.value = item.value;
|
||||
}
|
||||
@ -415,7 +429,8 @@ diyStore.editComponent.swiper.list.forEach((item: any) => {
|
||||
})
|
||||
|
||||
const activeNames = ref(['tab', 'swiper'])
|
||||
const handleChange = (val: string[]) => {}
|
||||
const handleChange = (val: string[]) => {
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
loadDiyPageList()
|
||||
@ -424,11 +439,11 @@ onMounted(() => {
|
||||
const addHotWordItem = () => {
|
||||
diyStore.editComponent.search.hotWord.list.push({
|
||||
id: diyStore.generateRandom(),
|
||||
text : '关键词',
|
||||
text: '关键词',
|
||||
})
|
||||
}
|
||||
|
||||
const tabClear = (index:any) => {
|
||||
const tabClear = (index: any) => {
|
||||
diyStore.editComponent.tab.list[index].diy_id = 0;
|
||||
diyStore.editComponent.tab.list[index].diy_title = '';
|
||||
}
|
||||
@ -436,10 +451,10 @@ const tabClear = (index:any) => {
|
||||
const addTabItem = () => {
|
||||
diyStore.editComponent.tab.list.push({
|
||||
id: diyStore.generateRandom(),
|
||||
text : '分类名称', // 最多4个字
|
||||
source : 'diy_page', // 数据源类型,微页面:diy_page
|
||||
diy_id : '',
|
||||
diy_title : ''
|
||||
text: '分类名称', // 最多4个字
|
||||
source: 'diy_page', // 数据源类型,微页面:diy_page
|
||||
diy_id: '',
|
||||
diy_title: ''
|
||||
})
|
||||
}
|
||||
|
||||
@ -507,8 +522,7 @@ const diyPageTable = reactive({
|
||||
total: 0,
|
||||
loading: true,
|
||||
data: [],
|
||||
searchParam: {
|
||||
}
|
||||
searchParam: {}
|
||||
})
|
||||
const diyPageTableRef = ref<InstanceType<typeof ElTable>>()
|
||||
|
||||
@ -552,7 +566,7 @@ const loadDiyPageList = (page: number = 1) => {
|
||||
}
|
||||
|
||||
// 选择微页面
|
||||
let currDiyPage:any = {}
|
||||
let currDiyPage: any = {}
|
||||
let currTabIndexForDiyPage = 0;
|
||||
const handleCurrentDiyPageChange = (val: string | any[]) => {
|
||||
currDiyPage = val
|
||||
@ -564,7 +578,7 @@ const saveDiyPageId = () => {
|
||||
diyPageShowDialog.value = false
|
||||
}
|
||||
|
||||
const diyPageShowDialogOpen = (index:any) => {
|
||||
const diyPageShowDialogOpen = (index: any) => {
|
||||
diyPageShowDialog.value = true
|
||||
currTabIndexForDiyPage = index;
|
||||
if (currDiyPage) {
|
||||
@ -593,28 +607,28 @@ const addImageAd = () => {
|
||||
})
|
||||
}
|
||||
|
||||
const selectImg = (url:string) => {
|
||||
const selectImg = (url: string) => {
|
||||
handleHeight(true)
|
||||
}
|
||||
|
||||
const changeSwiperStyle = (value:any) => {
|
||||
const changeSwiperStyle = (value: any) => {
|
||||
handleHeight(true)
|
||||
}
|
||||
|
||||
// 处理高度
|
||||
const handleHeight = (isCalcHeight:boolean = false)=> {
|
||||
const handleHeight = (isCalcHeight: boolean = false) => {
|
||||
diyStore.editComponent.swiper.list.forEach((item: any, index: number) => {
|
||||
const image = new Image()
|
||||
image.src = img(item.imageUrl)
|
||||
image.onload = async () => {
|
||||
image.onload = async() => {
|
||||
item.imgWidth = image.width
|
||||
item.imgHeight = image.height
|
||||
// 计算第一张图片高度
|
||||
if (isCalcHeight && index == 0) {
|
||||
const ratio = item.imgHeight / item.imgWidth
|
||||
if(diyStore.editComponent.swiper.swiperStyle == 'style-1') {
|
||||
if (diyStore.editComponent.swiper.swiperStyle == 'style-1') {
|
||||
item.width = 375 * 0.92 // 0.92:前端缩放比例
|
||||
}else{
|
||||
} else {
|
||||
item.width = 355
|
||||
}
|
||||
item.height = item.width * ratio
|
||||
@ -630,12 +644,13 @@ defineExpose({})
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
<style lang="scss">
|
||||
.select-diy-page-input .el-input__inner{
|
||||
cursor: pointer;
|
||||
}
|
||||
.collapse-wrap{
|
||||
.el-collapse-item__header{
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
.select-diy-page-input .el-input__inner {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.collapse-wrap {
|
||||
.el-collapse-item__header {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap float-btn" v-show="diyStore.editTab == 'content'">
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap float-btn" v-show="diyStore.editTab == 'content'">
|
||||
|
||||
<div class="edit-attr-item-wrap">
|
||||
<div class="edit-attr-item-wrap">
|
||||
<!-- <h3 class="mb-[10px]">{{ t('selectStyle') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('selectStyle')" class="flex">
|
||||
@ -28,63 +28,68 @@
|
||||
</template>
|
||||
|
||||
</el-dialog> -->
|
||||
<h3 class="mb-[10px]">{{ t('floatBtnButton') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('floatBtnButton')">
|
||||
<span>{{ selectTemplate.name }}</span>
|
||||
<h3 class="mb-[10px]">{{ t('floatBtnButton') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('floatBtnButton')">
|
||||
<span>{{ selectTemplate.name }}</span>
|
||||
<ul class="ml-[10px] flex items-center">
|
||||
<template v-for="(item,i) in templateList" :key="i">
|
||||
<li v-if="diyStore.editComponent.style==='style-1'||(diyStore.editComponent.style==='style-2'&&i>1)" :class="['w-[50px] h-[32px] flex items-center justify-center border-solid border-[1px] border-[#eee] cursor-pointer', {'border-r-transparent': templateList.length != (i+1)}, (item.className == diyStore.editComponent.bottomPosition) ? '!border-[var(--el-color-primary)]' : '' ]" @click="changeTemplateList(item)">
|
||||
<li v-if="diyStore.editComponent.style==='style-1'||(diyStore.editComponent.style==='style-2'&&i>1)"
|
||||
:class="['w-[50px] h-[32px] flex items-center justify-center border-solid border-[1px] border-[#eee] cursor-pointer', {'border-r-transparent': templateList.length != (i+1)}, (item.className == diyStore.editComponent.bottomPosition) ? '!border-[var(--el-color-primary)]' : '' ]"
|
||||
@click="changeTemplateList(item)">
|
||||
<span :class="['iconfont !text-[20px]', item.src]"></span>
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
</el-form-item>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('floatBtnOffset')">
|
||||
<el-slider v-model="diyStore.editComponent.offset" show-input size="small" class="ml-[10px] diy-nav-slider" :max="100"/>
|
||||
</el-form-item>
|
||||
<el-slider v-model="diyStore.editComponent.offset" show-input size="small" class="ml-[10px] diy-nav-slider" :max="100" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('lateralBtnOffset')">
|
||||
<el-slider v-model="diyStore.editComponent.lateralOffset" show-input size="small" class="ml-[10px] diy-nav-slider" :max="15" :min="-10"/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('floatBtnImageSet') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-slider v-model="diyStore.editComponent.lateralOffset" show-input size="small" class="ml-[10px] diy-nav-slider" :max="15" :min="-10" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('floatBtnImageSet') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('floatBtnImageSize')">
|
||||
<el-slider v-model="diyStore.editComponent.imageSize" show-input size="small" class="ml-[10px] diy-nav-slider" :min="30" :max="100"/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('floatBtnAroundRadius')">
|
||||
<el-slider v-model="diyStore.editComponent.aroundRadius" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50"/>
|
||||
</el-form-item>
|
||||
<el-slider v-model="diyStore.editComponent.imageSize" show-input size="small" class="ml-[10px] diy-nav-slider" :min="30" :max="100" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('floatBtnAroundRadius')">
|
||||
<el-slider v-model="diyStore.editComponent.aroundRadius" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50" />
|
||||
</el-form-item>
|
||||
|
||||
<div class="text-[12px] text-[#999] mb-[15px] mt-[5px]">{{t('floatBtnImageSuggest')}}</div>
|
||||
<div ref="imageBoxRef">
|
||||
<div v-for="(item,index) in diyStore.editComponent.list" :key="item.id" class="item-wrap p-[10px] pb-0 relative border border-dashed border-gray-300 mb-[16px]">
|
||||
<el-form-item :label="t('image')">
|
||||
<upload-image v-model="item.imageUrl" :limit="1" />
|
||||
</el-form-item>
|
||||
<div class="text-[12px] text-[#999] mb-[15px] mt-[5px]">{{ t('floatBtnImageSuggest') }}</div>
|
||||
<div ref="imageBoxRef">
|
||||
<div v-for="(item,index) in diyStore.editComponent.list" :key="item.id"
|
||||
class="item-wrap p-[10px] pb-0 relative border border-dashed border-gray-300 mb-[16px]">
|
||||
<el-form-item :label="t('image')">
|
||||
<upload-image v-model="item.imageUrl" :limit="1" />
|
||||
</el-form-item>
|
||||
|
||||
<div class="del absolute cursor-pointer z-[2] top-[-8px] right-[-8px]" v-show="diyStore.editComponent.list.length > 1" @click="diyStore.editComponent.list.splice(index,1)">
|
||||
<icon name="element CircleCloseFilled" color="#bbb" size="20px"/>
|
||||
</div>
|
||||
<div class="del absolute cursor-pointer z-[2] top-[-8px] right-[-8px]"
|
||||
v-show="diyStore.editComponent.list.length > 1"
|
||||
@click="diyStore.editComponent.list.splice(index,1)">
|
||||
<icon name="element CircleCloseFilled" color="#bbb" size="20px" />
|
||||
</div>
|
||||
|
||||
<el-form-item :label="t('link')">
|
||||
<diy-link v-model="item.link"/>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</div>
|
||||
</el-form>
|
||||
<el-form-item :label="t('link')">
|
||||
<diy-link v-model="item.link" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
</div>
|
||||
</el-form>
|
||||
|
||||
<el-button v-show="diyStore.editComponent.list.length < 3" class="w-full" @click="addImageAd">{{ t('addImageAd') }}</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
</div>
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
@ -94,10 +99,10 @@ import { t } from '@/lang'
|
||||
import Sortable from 'sortablejs'
|
||||
import useDiyStore from '@/stores/modules/diy'
|
||||
import { img } from '@/utils/common'
|
||||
import { min, range } from 'lodash-es'
|
||||
import { range } from 'lodash-es'
|
||||
|
||||
const diyStore = useDiyStore()
|
||||
diyStore.editComponent.ignore = ['pageBgColor','marginTop','marginBottom','marginBoth','componentBgUrl'] // 忽略公共属性
|
||||
diyStore.editComponent.ignore = ['pageBgColor', 'marginTop', 'marginBottom', 'marginBoth', 'componentBgUrl'] // 忽略公共属性
|
||||
|
||||
// 组件验证
|
||||
diyStore.editComponent.verify = (index: number) => {
|
||||
@ -137,7 +142,7 @@ const showCouponStyle = () => {
|
||||
// }
|
||||
// ])
|
||||
//风格点击
|
||||
const changeCouponStyle = (item:any) => {
|
||||
const changeCouponStyle = (item: any) => {
|
||||
selectCouponStyle.title = item.title;
|
||||
selectCouponStyle.value = item.value;
|
||||
}
|
||||
|
||||
@ -1,145 +1,150 @@
|
||||
<template>
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('graphicNavModeTitle') }}</h3>
|
||||
<el-form label-width="90px" class="px-[10px]">
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('graphicNavModeTitle') }}</h3>
|
||||
<el-form label-width="90px" class="px-[10px]">
|
||||
|
||||
<el-form-item :label="t('layoutMode')">
|
||||
<el-radio-group v-model="diyStore.editComponent.layout">
|
||||
<el-radio :label="'horizontal'">{{t('layoutModeHorizontal')}}</el-radio>
|
||||
<el-radio :label="'vertical'">{{t('layoutModeVertical')}}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('layoutMode')">
|
||||
<el-radio-group v-model="diyStore.editComponent.layout">
|
||||
<el-radio :label="'horizontal'">{{ t('layoutModeHorizontal') }}</el-radio>
|
||||
<el-radio :label="'vertical'">{{ t('layoutModeVertical') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('graphicNavSelectMode')">
|
||||
<el-radio-group v-model="diyStore.editComponent.mode">
|
||||
<el-radio :label="'graphic'">{{t('graphicNavModeGraphic')}}</el-radio>
|
||||
<el-radio :label="'img'">{{t('graphicNavModeImg')}}</el-radio>
|
||||
<el-radio :label="'text'">{{t('graphicNavModeText')}}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('graphicNavSelectMode')">
|
||||
<el-radio-group v-model="diyStore.editComponent.mode">
|
||||
<el-radio :label="'graphic'">{{ t('graphicNavModeGraphic') }}</el-radio>
|
||||
<el-radio :label="'img'">{{ t('graphicNavModeImg') }}</el-radio>
|
||||
<el-radio :label="'text'">{{ t('graphicNavModeText') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
<view v-show="diyStore.editComponent.layout == 'horizontal'">
|
||||
<view v-show="diyStore.editComponent.layout == 'horizontal'">
|
||||
|
||||
<el-form-item :label="t('graphicNavPageCount')">
|
||||
<el-radio-group v-model="diyStore.editComponent.pageCount" @change="changePageCount">
|
||||
<el-radio :label="1">{{t('singleLine')}}</el-radio>
|
||||
<el-radio :label="2">{{t('multiline')}}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('graphicNavPageCount')">
|
||||
<el-radio-group v-model="diyStore.editComponent.pageCount" @change="changePageCount">
|
||||
<el-radio :label="1">{{ t('singleLine') }}</el-radio>
|
||||
<el-radio :label="2">{{ t('multiline') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('graphicNavShowStyle')">
|
||||
<el-radio-group v-model="diyStore.editComponent.showStyle" @change="changeShowStyle">
|
||||
<el-radio :label="'fixed'">{{t('graphicNavStyleFixed')}}</el-radio>
|
||||
<el-radio :label="'singleSlide'">{{diyStore.editComponent.pageCount == 2 ? t('graphicNavStyleMultiLine') : t('graphicNavStyleSingleSlide')}}</el-radio>
|
||||
<el-radio :label="'pageSlide'">{{t('graphicNavStylePageSlide')}}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('graphicNavShowStyle')">
|
||||
<el-radio-group v-model="diyStore.editComponent.showStyle" @change="changeShowStyle">
|
||||
<el-radio :label="'fixed'">{{ t('graphicNavStyleFixed') }}</el-radio>
|
||||
<el-radio :label="'singleSlide'">{{ diyStore.editComponent.pageCount == 2 ? t('graphicNavStyleMultiLine') : t('graphicNavStyleSingleSlide') }}</el-radio>
|
||||
<el-radio :label="'pageSlide'">{{ t('graphicNavStylePageSlide') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('graphicNavRowCount')">
|
||||
<el-radio-group v-model="diyStore.editComponent.rowCount">
|
||||
<el-radio :label="3">3{{t('piece')}}</el-radio>
|
||||
<el-radio :label="4">4{{t('piece')}}</el-radio>
|
||||
<el-radio :label="5">5{{t('piece')}}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</view>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('graphicNavSetLabel') }}</h3>
|
||||
<el-form label-width="90px" class="px-[10px]">
|
||||
<el-form-item :label="t('graphicNavRowCount')">
|
||||
<el-radio-group v-model="diyStore.editComponent.rowCount">
|
||||
<el-radio :label="3">3{{ t('piece') }}</el-radio>
|
||||
<el-radio :label="4">4{{ t('piece') }}</el-radio>
|
||||
<el-radio :label="5">5{{ t('piece') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</view>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('graphicNavSetLabel') }}</h3>
|
||||
<el-form label-width="90px" class="px-[10px]">
|
||||
|
||||
<p class="text-sm text-gray-400 mb-[10px]">{{ t('graphicNavTips') }}</p>
|
||||
<p class="text-sm text-gray-400 mb-[10px]">{{ t('graphicNavTips') }}</p>
|
||||
|
||||
<div ref="imageBoxRef">
|
||||
<div v-for="(item,index) in diyStore.editComponent.list" :key="item.id" class="item-wrap p-[10px] pb-0 relative border border-dashed border-gray-300 mb-[16px]">
|
||||
<el-form-item :label="t('image')" v-show="diyStore.editComponent.mode === 'graphic' || diyStore.editComponent.mode === 'img'">
|
||||
<upload-image v-model="item.imageUrl" :limit="1"/>
|
||||
</el-form-item>
|
||||
<div ref="imageBoxRef">
|
||||
<div v-for="(item,index) in diyStore.editComponent.list" :key="item.id"
|
||||
class="item-wrap p-[10px] pb-0 relative border border-dashed border-gray-300 mb-[16px]">
|
||||
<el-form-item :label="t('image')" v-show="diyStore.editComponent.mode === 'graphic' || diyStore.editComponent.mode === 'img'">
|
||||
<upload-image v-model="item.imageUrl" :limit="1" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('graphicNavTitle')" v-show="diyStore.editComponent.mode === 'graphic' || diyStore.editComponent.mode === 'text'">
|
||||
<el-input v-model.trim="item.title" :placeholder="t('graphicNavTitlePlaceholder')" clearable maxlength="20" show-word-limit/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('graphicNavTitle')" v-show="diyStore.editComponent.mode === 'graphic' || diyStore.editComponent.mode === 'text'">
|
||||
<el-input v-model.trim="item.title" :placeholder="t('graphicNavTitlePlaceholder')" clearable maxlength="20" show-word-limit />
|
||||
</el-form-item>
|
||||
|
||||
<div class="del absolute cursor-pointer z-[2] top-[-8px] right-[-8px]" v-show="diyStore.editComponent.list.length > 1" @click="diyStore.editComponent.list.splice(index,1)">
|
||||
<icon name="element CircleCloseFilled" color="#bbb" size="20px"/>
|
||||
</div>
|
||||
<div class="del absolute cursor-pointer z-[2] top-[-8px] right-[-8px]"
|
||||
v-show="diyStore.editComponent.list.length > 1"
|
||||
@click="diyStore.editComponent.list.splice(index,1)">
|
||||
<icon name="element CircleCloseFilled" color="#bbb" size="20px" />
|
||||
</div>
|
||||
|
||||
<el-form-item :label="t('link')">
|
||||
<diy-link v-model="item.link"/>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</div>
|
||||
<el-form-item :label="t('link')">
|
||||
<diy-link v-model="item.link" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-button v-show="diyStore.editComponent.list.length < 50" class="w-full" @click="addGraphicNav">{{ t('addGraphicNav') }}</el-button>
|
||||
<el-button v-show="diyStore.editComponent.list.length < 50" class="w-full" @click="addGraphicNav">
|
||||
{{ t('addGraphicNav') }}
|
||||
</el-button>
|
||||
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
<div class="edit-attr-item-wrap" v-show="['graphic','img'].includes(diyStore.editComponent.mode)">
|
||||
<h3 class="mb-[10px]">{{ t('graphicNavImageSet') }}</h3>
|
||||
<el-form label-width="90px" class="px-[10px]">
|
||||
<el-form-item :label="t('graphicNavImageSize')">
|
||||
<el-slider v-model="diyStore.editComponent.imageSize" show-input size="small" class="ml-[10px] diy-nav-slider" :min="20" :max="60"/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('graphicNavAroundRadius')">
|
||||
<el-slider v-model="diyStore.editComponent.aroundRadius" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50"/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="edit-attr-item-wrap" v-show="['graphic','text'].includes(diyStore.editComponent.mode)">
|
||||
<h3 class="mb-[10px]">{{ t('textSet') }}</h3>
|
||||
<el-form label-width="90px" class="px-[10px]">
|
||||
<el-form-item :label="t('textFontSize')">
|
||||
<el-slider v-model="diyStore.editComponent.font.size" show-input size="small" class="ml-[10px] diy-nav-slider" :min="12" :max="16"/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('textFontWeight')">
|
||||
<el-radio-group v-model="diyStore.editComponent.font.weight">
|
||||
<el-radio :label="'normal'">{{t('fontWeightNormal')}}</el-radio>
|
||||
<el-radio :label="'bold'">{{t('fontWeightBold')}}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('textColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.font.color" show-alpha :predefine="diyStore.predefineColors"/>
|
||||
</el-form-item>
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
<div class="edit-attr-item-wrap" v-show="['graphic','img'].includes(diyStore.editComponent.mode)">
|
||||
<h3 class="mb-[10px]">{{ t('graphicNavImageSet') }}</h3>
|
||||
<el-form label-width="90px" class="px-[10px]">
|
||||
<el-form-item :label="t('graphicNavImageSize')">
|
||||
<el-slider v-model="diyStore.editComponent.imageSize" show-input size="small" class="ml-[10px] diy-nav-slider" :min="20" :max="60" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('graphicNavAroundRadius')">
|
||||
<el-slider v-model="diyStore.editComponent.aroundRadius" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="edit-attr-item-wrap" v-show="['graphic','text'].includes(diyStore.editComponent.mode)">
|
||||
<h3 class="mb-[10px]">{{ t('textSet') }}</h3>
|
||||
<el-form label-width="90px" class="px-[10px]">
|
||||
<el-form-item :label="t('textFontSize')">
|
||||
<el-slider v-model="diyStore.editComponent.font.size" show-input size="small" class="ml-[10px] diy-nav-slider" :min="12" :max="16" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('textFontWeight')">
|
||||
<el-radio-group v-model="diyStore.editComponent.font.weight">
|
||||
<el-radio :label="'normal'">{{ t('fontWeightNormal') }}</el-radio>
|
||||
<el-radio :label="'bold'">{{ t('fontWeightBold') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('textColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.font.color" show-alpha :predefine="diyStore.predefineColors" />
|
||||
</el-form-item>
|
||||
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="edit-attr-item-wrap" v-show="diyStore.editComponent.showStyle == 'pageSlide' && diyStore.editComponent.layout == 'horizontal'">
|
||||
<h3 class="mb-[10px]">{{ t('carouselSearchSwiperIndicatorSet') }}</h3>
|
||||
<el-form label-width="100px" class="px-[10px]">
|
||||
<el-form-item :label="t('carouselSearchSwiperIndicatorStyle')">
|
||||
<el-radio-group v-model="diyStore.editComponent.swiper.indicatorStyle">
|
||||
<el-radio label="style-1">{{ t('carouselSearchSwiperIndicatorStyle1') }}</el-radio>
|
||||
<el-radio label="style-2">{{ t('carouselSearchSwiperIndicatorStyle2') }}</el-radio>
|
||||
<el-radio label="style-3">{{ t('carouselSearchSwiperIndicatorStyle3') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('carouselSearchSwiperIndicatorAlign')">
|
||||
<el-radio-group v-model="diyStore.editComponent.swiper.indicatorAlign">
|
||||
<el-radio label="left">{{ t('alignLeft') }}</el-radio>
|
||||
<el-radio label="center">{{ t('alignCenter') }}</el-radio>
|
||||
<el-radio label="right">{{ t('alignRight') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('noColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.swiper.indicatorColor" show-alpha :predefine="diyStore.predefineColors"/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('selectColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.swiper.indicatorActiveColor" show-alpha :predefine="diyStore.predefineColors"/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="edit-attr-item-wrap" v-show="diyStore.editComponent.showStyle == 'pageSlide' && diyStore.editComponent.layout == 'horizontal'">
|
||||
<h3 class="mb-[10px]">{{ t('carouselSearchSwiperIndicatorSet') }}</h3>
|
||||
<el-form label-width="100px" class="px-[10px]">
|
||||
<el-form-item :label="t('carouselSearchSwiperIndicatorStyle')">
|
||||
<el-radio-group v-model="diyStore.editComponent.swiper.indicatorStyle">
|
||||
<el-radio label="style-1">{{ t('carouselSearchSwiperIndicatorStyle1') }}</el-radio>
|
||||
<el-radio label="style-2">{{ t('carouselSearchSwiperIndicatorStyle2') }}</el-radio>
|
||||
<el-radio label="style-3">{{ t('carouselSearchSwiperIndicatorStyle3') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('carouselSearchSwiperIndicatorAlign')">
|
||||
<el-radio-group v-model="diyStore.editComponent.swiper.indicatorAlign">
|
||||
<el-radio label="left">{{ t('alignLeft') }}</el-radio>
|
||||
<el-radio label="center">{{ t('alignCenter') }}</el-radio>
|
||||
<el-radio label="right">{{ t('alignRight') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('noColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.swiper.indicatorColor" show-alpha :predefine="diyStore.predefineColors" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('selectColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.swiper.indicatorActiveColor" show-alpha :predefine="diyStore.predefineColors" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
@ -184,7 +189,7 @@ watch(
|
||||
diyStore.editComponent.list.forEach((item: any) => {
|
||||
const image = new Image()
|
||||
image.src = img(item.imageUrl)
|
||||
image.onload = async () => {
|
||||
image.onload = async() => {
|
||||
item.imgWidth = image.width
|
||||
item.imgHeight = image.height
|
||||
}
|
||||
@ -232,31 +237,31 @@ onMounted(() => {
|
||||
})
|
||||
})
|
||||
|
||||
const changePageCount = (value:any)=>{
|
||||
if(value == '1'){
|
||||
const changePageCount = (value: any) => {
|
||||
if (value == '1') {
|
||||
diyStore.editComponent.showStyle = 'singleSlide';
|
||||
}else if(value == '2'){
|
||||
} else if (value == '2') {
|
||||
diyStore.editComponent.showStyle = 'fixed';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({})
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.edit-graphic-nav {
|
||||
.edit-graphic-nav {
|
||||
|
||||
.item-wrap {
|
||||
.del {
|
||||
display: none;
|
||||
}
|
||||
.item-wrap {
|
||||
.del {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.del {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
.del {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,22 +1,22 @@
|
||||
<template>
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('blankHeightSet') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('blankHeight')">
|
||||
<el-slider v-model="diyStore.editComponent.height" show-input size="small" max="200" class="ml-[10px] diy-nav-slider"/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('blankHeightSet') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('blankHeight')">
|
||||
<el-slider v-model="diyStore.editComponent.height" show-input size="small" max="200" class="ml-[10px] diy-nav-slider" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
</div>
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
|
||||
@ -1,31 +1,32 @@
|
||||
<template>
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('horzLineStyle') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('styleLabel')">
|
||||
<el-radio-group v-model="diyStore.editComponent.borderStyle">
|
||||
<el-radio label="solid">{{ t('horzLineStyleSolid') }}</el-radio>
|
||||
<el-radio label="dashed">{{ t('horzLineStyleDashed') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('horzLineBorderColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.borderColor" show-alpha :predefine="diyStore.predefineColors"/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('horzLineBorderWidth')">
|
||||
<el-slider v-model="diyStore.editComponent.borderWidth" show-input size="small" class="ml-[10px] diy-nav-slider" :min="1" :max="10"/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('horzLineStyle') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('styleLabel')">
|
||||
<el-radio-group v-model="diyStore.editComponent.borderStyle">
|
||||
<el-radio label="solid">{{ t('horzLineStyleSolid') }}</el-radio>
|
||||
<el-radio label="dashed">{{ t('horzLineStyleDashed') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('horzLineBorderColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.borderColor" show-alpha :predefine="diyStore.predefineColors" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('horzLineBorderWidth')">
|
||||
<el-slider v-model="diyStore.editComponent.borderWidth" show-input size="small"
|
||||
class="ml-[10px] diy-nav-slider" :min="1" :max="10" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
</div>
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
@ -34,7 +35,7 @@ import { t } from '@/lang'
|
||||
import useDiyStore from '@/stores/modules/diy'
|
||||
|
||||
const diyStore = useDiyStore()
|
||||
diyStore.editComponent.ignore = ['pageBgColor','componentBgColor', 'componentBgUrl', 'topRounded', 'bottomRounded'] // 忽略公共属性
|
||||
diyStore.editComponent.ignore = ['pageBgColor', 'componentBgColor', 'componentBgUrl', 'topRounded', 'bottomRounded'] // 忽略公共属性
|
||||
|
||||
defineExpose({})
|
||||
|
||||
|
||||
@ -1,34 +1,34 @@
|
||||
<template>
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('hotAreaSet') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('hotAreaSet') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
|
||||
<div ref="imageBoxRef">
|
||||
<div class="item-wrap p-[10px] pb-0 relative border border-dashed border-gray-300 mb-[16px]">
|
||||
<el-form-item :label="t('hotAreaBackground')">
|
||||
<upload-image v-model="diyStore.editComponent.imageUrl" :limit="1" @change="selectImg"/>
|
||||
</el-form-item>
|
||||
<div ref="imageBoxRef">
|
||||
<div class="item-wrap p-[10px] pb-0 relative border border-dashed border-gray-300 mb-[16px]">
|
||||
<el-form-item :label="t('hotAreaBackground')">
|
||||
<upload-image v-model="diyStore.editComponent.imageUrl" :limit="1" @change="selectImg" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('hotAreaSet')">
|
||||
<heat-map v-model="diyStore.editComponent"/>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</div>
|
||||
<el-form-item :label="t('hotAreaSet')">
|
||||
<heat-map v-model="diyStore.editComponent" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</el-form>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
</div>
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
@ -59,7 +59,7 @@ const selectImg = (url: string) => {
|
||||
const handleHeight = () => {
|
||||
const image = new Image()
|
||||
image.src = img(diyStore.editComponent.imageUrl)
|
||||
image.onload = async () => {
|
||||
image.onload = async() => {
|
||||
diyStore.editComponent.imgWidth = image.width
|
||||
diyStore.editComponent.imgHeight = image.height
|
||||
}
|
||||
|
||||
@ -1,50 +1,54 @@
|
||||
<template>
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('imageSet') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
|
||||
<el-form-item :label="t('sameScreen')" v-if="diyStore.currentIndex == 0">
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('imageSet') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
|
||||
<el-form-item :label="t('sameScreen')" v-if="diyStore.currentIndex == 0">
|
||||
<el-switch v-model="diyStore.editComponent.isSameScreen" />
|
||||
<div class="text-sm text-gray-400 leading-[1.4]">{{ t('imageAdsSameScreenTips') }}</div>
|
||||
</el-form-item>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('imageHeight')" class="display-block">
|
||||
<el-input v-model.trim="diyStore.editComponent.imageHeight" :placeholder="t('imageHeightPlaceholder')" clearable maxlength="10" @blur="blurImageHeight">
|
||||
<template #append>px</template>
|
||||
</el-input>
|
||||
<div class="text-sm text-gray-400 mb-[10px]">{{ t('imageAdsTips') }}</div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('imageHeight')" class="display-block">
|
||||
<el-input v-model.trim="diyStore.editComponent.imageHeight" :placeholder="t('imageHeightPlaceholder')" clearable maxlength="10" @blur="blurImageHeight">
|
||||
<template #append>px</template>
|
||||
</el-input>
|
||||
<div class="text-sm text-gray-400 mb-[10px]">{{ t('imageAdsTips') }}</div>
|
||||
</el-form-item>
|
||||
|
||||
<div ref="imageBoxRef">
|
||||
<div v-for="(item,index) in diyStore.editComponent.list" :key="item.id" class="item-wrap p-[10px] pb-0 relative border border-dashed border-gray-300 mb-[16px]">
|
||||
<el-form-item :label="t('image')">
|
||||
<upload-image v-model="item.imageUrl" :limit="1" @change="selectImg" />
|
||||
</el-form-item>
|
||||
<div ref="imageBoxRef">
|
||||
<div v-for="(item,index) in diyStore.editComponent.list" :key="item.id" class="item-wrap p-[10px] pb-0 relative border border-dashed border-gray-300 mb-[16px]">
|
||||
<el-form-item :label="t('image')">
|
||||
<upload-image v-model="item.imageUrl" :limit="1" @change="selectImg" />
|
||||
</el-form-item>
|
||||
|
||||
<div class="del absolute cursor-pointer z-[2] top-[-8px] right-[-8px]" v-show="diyStore.editComponent.list.length > 1" @click="diyStore.editComponent.list.splice(index,1)">
|
||||
<icon name="element CircleCloseFilled" color="#bbb" size="20px"/>
|
||||
</div>
|
||||
<div class="del absolute cursor-pointer z-[2] top-[-8px] right-[-8px]"
|
||||
v-show="diyStore.editComponent.list.length > 1"
|
||||
@click="diyStore.editComponent.list.splice(index,1)">
|
||||
<icon name="element CircleCloseFilled" color="#bbb" size="20px" />
|
||||
</div>
|
||||
|
||||
<el-form-item :label="t('link')">
|
||||
<diy-link v-model="item.link"/>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</div>
|
||||
<el-form-item :label="t('link')">
|
||||
<diy-link v-model="item.link" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-button v-show="diyStore.editComponent.list.length < 10" class="w-full" @click="addImageAd">{{ t('addImageAd') }}</el-button>
|
||||
<el-button v-show="diyStore.editComponent.list.length < 10" class="w-full" @click="addImageAd">
|
||||
{{ t('addImageAd') }}
|
||||
</el-button>
|
||||
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
</div>
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
@ -105,22 +109,22 @@ const addImageAd = () => {
|
||||
})
|
||||
}
|
||||
|
||||
const selectImg = (url:string) => {
|
||||
const selectImg = (url: string) => {
|
||||
handleHeight(true)
|
||||
}
|
||||
|
||||
// 处理高度
|
||||
const handleHeight = (isCalcHeight:boolean = false)=> {
|
||||
const handleHeight = (isCalcHeight: boolean = false) => {
|
||||
diyStore.editComponent.list.forEach((item: any, index: number) => {
|
||||
const image = new Image()
|
||||
image.src = img(item.imageUrl)
|
||||
image.onload = async () => {
|
||||
image.onload = async() => {
|
||||
item.imgWidth = image.width
|
||||
item.imgHeight = image.height
|
||||
// 计算第一张图片高度
|
||||
if (isCalcHeight && index == 0) {
|
||||
const ratio = item.imgHeight / item.imgWidth
|
||||
item.width = 375 - (diyStore.editComponent.margin.both*2)
|
||||
item.width = 375 - (diyStore.editComponent.margin.both * 2)
|
||||
item.height = item.width * ratio
|
||||
diyStore.editComponent.imageHeight = parseInt(item.height)
|
||||
}
|
||||
@ -158,18 +162,18 @@ defineExpose({})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.edit-image-ads {
|
||||
.edit-image-ads {
|
||||
|
||||
.item-wrap {
|
||||
.del {
|
||||
display: none;
|
||||
}
|
||||
.item-wrap {
|
||||
.del {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.del {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
.del {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,30 +1,30 @@
|
||||
<template>
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('memberStyle') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('bgUrl')">
|
||||
<upload-image v-model="diyStore.editComponent.bgUrl" :limit="1"/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('memberStyle') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('bgUrl')">
|
||||
<upload-image v-model="diyStore.editComponent.bgUrl" :limit="1" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('memberStyle') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('textColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.textColor"/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('memberStyle') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('textColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.textColor" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
</div>
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
||||
@ -1,46 +1,49 @@
|
||||
|
||||
<template>
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('selectStyle') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('selectStyle')" class="flex">
|
||||
<span class="text-primary flex-1 cursor-pointer" @click="showStyle">{{ diyStore.editComponent.styleName }}</span>
|
||||
<el-icon>
|
||||
<ArrowRight />
|
||||
</el-icon>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('selectStyle') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('selectStyle')" class="flex">
|
||||
<span class="text-primary flex-1 cursor-pointer"
|
||||
@click="showStyle">{{ diyStore.editComponent.styleName }}</span>
|
||||
<el-icon>
|
||||
<ArrowRight />
|
||||
</el-icon>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-dialog v-model="showDialog" :title="t('selectStyle')" width="660px">
|
||||
<el-dialog v-model="showDialog" :title="t('selectStyle')" width="660px">
|
||||
|
||||
<div class="flex flex-wrap">
|
||||
<template v-for="(item,index) in styleList" :key="index">
|
||||
<div :class="{ 'border-primary': selectStyle.value == item.value, '!mr-[0]': [(index+1)%3] == 0 }" @click="changeStyle(item)" class="flex my-[5px] items-center justify-center overflow-hidden w-[200px] h-[100px] mr-[12px] cursor-pointer border bg-gray-50">
|
||||
<img :src="img(item.url)" />
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class="flex flex-wrap">
|
||||
<template v-for="(item,index) in styleList" :key="index">
|
||||
<div
|
||||
:class="{ 'border-primary': selectStyle.value == item.value, '!mr-[0]': [(index+1)%3] == 0 }"
|
||||
@click="changeStyle(item)"
|
||||
class="flex my-[5px] items-center justify-center overflow-hidden w-[200px] h-[100px] mr-[12px] cursor-pointer border bg-gray-50">
|
||||
<img :src="img(item.url)" />
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="showDialog = false">{{ t('cancel') }}</el-button>
|
||||
<el-button type="primary" @click="confirmStyle">{{ t('confirm') }}</el-button>
|
||||
</span>
|
||||
</template>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="showDialog = false">{{ t('cancel') }}</el-button>
|
||||
<el-button type="primary" @click="confirmStyle">{{ t('confirm') }}</el-button>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
</el-dialog>
|
||||
</div>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
@ -50,7 +53,7 @@ import { img } from '@/utils/common'
|
||||
import { ref, reactive } from 'vue'
|
||||
|
||||
const diyStore = useDiyStore()
|
||||
diyStore.editComponent.ignore = ['componentBgColor','componentBgUrl'] // 忽略公共属性
|
||||
diyStore.editComponent.ignore = ['componentBgColor', 'componentBgUrl'] // 忽略公共属性
|
||||
|
||||
const selectStyle = reactive({
|
||||
title: diyStore.editComponent.styleName,
|
||||
@ -94,7 +97,7 @@ const styleList = reactive([
|
||||
}
|
||||
])
|
||||
|
||||
const changeStyle = (item:any) => {
|
||||
const changeStyle = (item: any) => {
|
||||
selectStyle.title = item.title;
|
||||
selectStyle.value = item.value;
|
||||
}
|
||||
@ -108,22 +111,22 @@ const confirmStyle = () => {
|
||||
|
||||
|
||||
const initStyle = (style: any) => {
|
||||
if (style == 'style-1') {
|
||||
diyStore.editComponent.bottomRounded = 0;
|
||||
diyStore.editComponent.topRounded = 12;
|
||||
} else if (style == 'style-2') {
|
||||
diyStore.editComponent.bottomRounded = 0;
|
||||
diyStore.editComponent.topRounded = 12;
|
||||
} else if (style == 'style-3') {
|
||||
diyStore.editComponent.bottomRounded = 12;
|
||||
diyStore.editComponent.topRounded = 12;
|
||||
} else if (style == 'style-4') {
|
||||
diyStore.editComponent.bottomRounded = 12;
|
||||
diyStore.editComponent.topRounded = 12;
|
||||
} else if (style == 'style-5') {
|
||||
diyStore.editComponent.bottomRounded = 12;
|
||||
diyStore.editComponent.topRounded = 12;
|
||||
}
|
||||
if (style == 'style-1') {
|
||||
diyStore.editComponent.bottomRounded = 0;
|
||||
diyStore.editComponent.topRounded = 12;
|
||||
} else if (style == 'style-2') {
|
||||
diyStore.editComponent.bottomRounded = 0;
|
||||
diyStore.editComponent.topRounded = 12;
|
||||
} else if (style == 'style-3') {
|
||||
diyStore.editComponent.bottomRounded = 12;
|
||||
diyStore.editComponent.topRounded = 12;
|
||||
} else if (style == 'style-4') {
|
||||
diyStore.editComponent.bottomRounded = 12;
|
||||
diyStore.editComponent.topRounded = 12;
|
||||
} else if (style == 'style-5') {
|
||||
diyStore.editComponent.bottomRounded = 12;
|
||||
diyStore.editComponent.topRounded = 12;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -1,101 +1,104 @@
|
||||
<template>
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap notice-content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('noticeStyle') }}</h3>
|
||||
<el-form label-width="90px" class="px-[10px]">
|
||||
<el-form-item :label="t('noticeType')">
|
||||
<el-radio-group v-model="diyStore.editComponent.noticeType">
|
||||
<el-radio label="img">{{ t('noticeTypeImg') }}</el-radio>
|
||||
<el-radio label="text">{{ t('noticeTypeText') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<div class="flex items-center flex-wrap py-[8px] px-[10px] bg-[#f4f3f7] rounded mb-[18px] mx-[18px]" v-show="diyStore.editComponent.noticeType == 'img'">
|
||||
<div :class="['mr-[10px] rounded cursor-pointer border-[1px] border-solid', {'border-[var(--el-color-primary)]': diyStore.editComponent.systemUrl == 'style_1' && diyStore.editComponent.imgType == 'system'}]">
|
||||
<img src="@/app/assets/images/diy/notice/style_1.png" :class="['h-[28px] px-[10px] py-[5px]']" @click="changeStyle('style_1')"/>
|
||||
</div>
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap notice-content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('noticeStyle') }}</h3>
|
||||
<el-form label-width="90px" class="px-[10px]">
|
||||
<el-form-item :label="t('noticeType')">
|
||||
<el-radio-group v-model="diyStore.editComponent.noticeType">
|
||||
<el-radio label="img">{{ t('noticeTypeImg') }}</el-radio>
|
||||
<el-radio label="text">{{ t('noticeTypeText') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<div class="flex items-center flex-wrap py-[8px] px-[10px] bg-[#f4f3f7] rounded mb-[18px] mx-[18px]" v-show="diyStore.editComponent.noticeType == 'img'">
|
||||
<div :class="['mr-[10px] rounded cursor-pointer border-[1px] border-solid', {'border-[var(--el-color-primary)]': diyStore.editComponent.systemUrl == 'style_1' && diyStore.editComponent.imgType == 'system'}]">
|
||||
<img src="@/app/assets/images/diy/notice/style_1.png" :class="['h-[28px] px-[10px] py-[5px]']" @click="changeStyle('style_1')" />
|
||||
</div>
|
||||
|
||||
<div :class="['mr-[10px] rounded cursor-pointer w-[100px] border-[1px] border-solid', {'border-[var(--el-color-primary)]': diyStore.editComponent.systemUrl == 'style_2' && diyStore.editComponent.imgType == 'system'}]">
|
||||
<img src="@/app/assets/images/diy/notice/style_2.png" class="px-[10px] py-[5px]" @click="changeStyle('style_2')"/>
|
||||
</div>
|
||||
<div @click.stop="diyStore.editComponent.imgType = 'diy'" :class="['mr-[10px] rounded cursor-pointer diy-upload-img border-[1px] border-solid', {'border-[var(--el-color-primary)]': (diyStore.editComponent.imageUrl && diyStore.editComponent.imgType == 'diy') }]">
|
||||
<upload-image v-model="diyStore.editComponent.imageUrl" :limit="1"/>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="['mr-[10px] rounded cursor-pointer w-[100px] border-[1px] border-solid', {'border-[var(--el-color-primary)]': diyStore.editComponent.systemUrl == 'style_2' && diyStore.editComponent.imgType == 'system'}]">
|
||||
<img src="@/app/assets/images/diy/notice/style_2.png" class="px-[10px] py-[5px]" @click="changeStyle('style_2')" />
|
||||
</div>
|
||||
<div @click.stop="diyStore.editComponent.imgType = 'diy'"
|
||||
:class="['mr-[10px] rounded cursor-pointer diy-upload-img border-[1px] border-solid', {'border-[var(--el-color-primary)]': (diyStore.editComponent.imageUrl && diyStore.editComponent.imgType == 'diy') }]">
|
||||
<upload-image v-model="diyStore.editComponent.imageUrl" :limit="1" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-form-item :label="t('noticeTitle')" v-show="diyStore.editComponent.noticeType == 'text'">
|
||||
<el-input v-model.trim="diyStore.editComponent.noticeTitle" :placeholder="t('titlePlaceholder')" clearable maxlength="20" show-word-limit/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('noticeTitle')" v-show="diyStore.editComponent.noticeType == 'text'">
|
||||
<el-input v-model.trim="diyStore.editComponent.noticeTitle" :placeholder="t('titlePlaceholder')" clearable maxlength="20" show-word-limit />
|
||||
</el-form-item>
|
||||
|
||||
</el-form>
|
||||
</el-form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('noticeText') }}</h3>
|
||||
<el-form label-width="90px" class="px-[10px]">
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('noticeText') }}</h3>
|
||||
<el-form label-width="90px" class="px-[10px]">
|
||||
|
||||
<el-form-item :label="t('noticeScrollWay')">
|
||||
<el-radio-group v-model="diyStore.editComponent.scrollWay">
|
||||
<el-radio label="upDown">{{ t('noticeUpDown') }}</el-radio>
|
||||
<el-radio label="horizontal">{{ t('noticeHorizontal') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('noticeShowType')">
|
||||
<el-radio-group v-model="diyStore.editComponent.showType">
|
||||
<el-radio label="popup">{{ t('noticeShowPopUp') }}</el-radio>
|
||||
<el-radio label="link">{{ t('noticeShowLink') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('noticeScrollWay')">
|
||||
<el-radio-group v-model="diyStore.editComponent.scrollWay">
|
||||
<el-radio label="upDown">{{ t('noticeUpDown') }}</el-radio>
|
||||
<el-radio label="horizontal">{{ t('noticeHorizontal') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('noticeShowType')">
|
||||
<el-radio-group v-model="diyStore.editComponent.showType">
|
||||
<el-radio label="popup">{{ t('noticeShowPopUp') }}</el-radio>
|
||||
<el-radio label="link">{{ t('noticeShowLink') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
<p class="text-sm text-gray-400 mb-[10px]">{{ t('dragMouseAdjustOrder') }}</p>
|
||||
<p class="text-sm text-gray-400 mb-[10px]">{{ t('dragMouseAdjustOrder') }}</p>
|
||||
|
||||
<div ref="noticeBoxRef">
|
||||
<div v-for="(item,index) in diyStore.editComponent.list" :key="item.id" class="item-wrap p-[10px] pb-0 relative border border-dashed border-gray-300 mb-[16px]">
|
||||
<div ref="noticeBoxRef">
|
||||
<div v-for="(item,index) in diyStore.editComponent.list" :key="item.id" class="item-wrap p-[10px] pb-0 relative border border-dashed border-gray-300 mb-[16px]">
|
||||
|
||||
<el-form-item :label="t('noticeText')">
|
||||
<el-input v-model.trim="item.text" :placeholder="t('noticePlaceholderText')" clearable maxlength="40" show-word-limit/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('noticeText')">
|
||||
<el-input v-model.trim="item.text" :placeholder="t('noticePlaceholderText')" clearable maxlength="40" show-word-limit />
|
||||
</el-form-item>
|
||||
|
||||
<div class="del absolute cursor-pointer z-[2] top-[-8px] right-[-8px]" v-show="diyStore.editComponent.list.length > 1" @click="diyStore.editComponent.list.splice(index,1)">
|
||||
<icon name="element CircleCloseFilled" color="#bbb" size="20px"/>
|
||||
</div>
|
||||
<div class="del absolute cursor-pointer z-[2] top-[-8px] right-[-8px]"
|
||||
v-show="diyStore.editComponent.list.length > 1"
|
||||
@click="diyStore.editComponent.list.splice(index,1)">
|
||||
<icon name="element CircleCloseFilled" color="#bbb" size="20px" />
|
||||
</div>
|
||||
|
||||
<el-form-item :label="t('link')" v-if="diyStore.editComponent.showType == 'link'">
|
||||
<diy-link v-model="item.link"/>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</div>
|
||||
<el-form-item :label="t('link')" v-if="diyStore.editComponent.showType == 'link'">
|
||||
<diy-link v-model="item.link" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-button class="w-full" @click="addNotice">{{ t('addNotice') }}</el-button>
|
||||
<el-button class="w-full" @click="addNotice">{{ t('addNotice') }}</el-button>
|
||||
|
||||
</el-form>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('textSet') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('textFontSize')">
|
||||
<el-slider v-model="diyStore.editComponent.fontSize" show-input size="small" class="ml-[10px] diy-nav-slider" :min="12" :max="20"/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('textFontWeight')">
|
||||
<el-radio-group v-model="diyStore.editComponent.fontWeight">
|
||||
<el-radio :label="'normal'">{{t('fontWeightNormal')}}</el-radio>
|
||||
<el-radio :label="'bold'">{{t('fontWeightBold')}}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('textColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.textColor"/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
</div>
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('textSet') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('textFontSize')">
|
||||
<el-slider v-model="diyStore.editComponent.fontSize" show-input size="small" class="ml-[10px] diy-nav-slider" :min="12" :max="20" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('textFontWeight')">
|
||||
<el-radio-group v-model="diyStore.editComponent.fontWeight">
|
||||
<el-radio :label="'normal'">{{ t('fontWeightNormal') }}</el-radio>
|
||||
<el-radio :label="'bold'">{{ t('fontWeightBold') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('textColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.textColor" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
@ -105,6 +108,7 @@ import useDiyStore from '@/stores/modules/diy'
|
||||
import { ref, watch, onMounted, nextTick } from 'vue'
|
||||
import { range } from 'lodash-es'
|
||||
import Sortable from 'sortablejs'
|
||||
|
||||
const diyStore = useDiyStore()
|
||||
diyStore.editComponent.ignore = [] // 忽略公共属性
|
||||
|
||||
@ -112,8 +116,8 @@ diyStore.editComponent.ignore = [] // 忽略公共属性
|
||||
diyStore.editComponent.verify = (index: number) => {
|
||||
const res = { code: true, message: '' }
|
||||
|
||||
if(diyStore.value[index].noticeType == 'text'){
|
||||
if(diyStore.value[index].noticeTitle == ''){
|
||||
if (diyStore.value[index].noticeType == 'text') {
|
||||
if (diyStore.value[index].noticeTitle == '') {
|
||||
res.code = false
|
||||
res.message = t('noticeTypeTextPlaceholder')
|
||||
return res
|
||||
@ -134,9 +138,7 @@ diyStore.editComponent.list.forEach((item: any) => {
|
||||
if (!item.id) item.id = diyStore.generateRandom()
|
||||
})
|
||||
|
||||
const selectStyle = ref(diyStore.editComponent.style)
|
||||
|
||||
const changeStyle = (value :any) => {
|
||||
const changeStyle = (value: any) => {
|
||||
diyStore.editComponent.systemUrl = value;
|
||||
diyStore.editComponent.imgType = 'system';
|
||||
}
|
||||
@ -144,11 +146,11 @@ const changeStyle = (value :any) => {
|
||||
watch(
|
||||
() => diyStore.editComponent.imageUrl,
|
||||
(newValue, oldValue) => {
|
||||
if(newValue){
|
||||
if (newValue) {
|
||||
diyStore.editComponent.imgType = 'diy';
|
||||
}else{
|
||||
changeStyle('style_1');
|
||||
}
|
||||
} else {
|
||||
changeStyle('style_1');
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
@ -185,26 +187,26 @@ defineExpose({})
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.notice-content-wrap {
|
||||
.add-notice-width {
|
||||
width: calc(100% - 20px);
|
||||
}
|
||||
.notice-content-wrap {
|
||||
.add-notice-width {
|
||||
width: calc(100% - 20px);
|
||||
}
|
||||
|
||||
.diy-upload-img {
|
||||
.image-wrap {
|
||||
width: 50px !important;
|
||||
height: 50px !important;
|
||||
margin-right: 0 !important;
|
||||
background: #fff;
|
||||
}
|
||||
.diy-upload-img {
|
||||
.image-wrap {
|
||||
width: 50px !important;
|
||||
height: 50px !important;
|
||||
margin-right: 0 !important;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.content-wrap {
|
||||
div {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
.content-wrap {
|
||||
div {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
@ -1,35 +1,36 @@
|
||||
<template>
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('pageContent') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]" @submit.prevent>
|
||||
<el-form-item :label="t('diyPageTitle')">
|
||||
<el-input v-model.trim="diyStore.pageTitle" :placeholder="t('diyPageTitlePlaceholder')" clearable maxlength="16" show-word-limit/>
|
||||
<div class="text-sm text-gray-400">{{ t('pageTitleTips') }}</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<!-- 表单布局 页面设置 -->
|
||||
<slot name="content"></slot>
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('statusBarContent') }}</h3>
|
||||
<h3 class="mb-[10px]">{{ t('pageContent') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]" @submit.prevent>
|
||||
<el-form-item :label="t('diyPageTitle')">
|
||||
<el-input v-model.trim="diyStore.pageTitle" :placeholder="t('diyPageTitlePlaceholder')" clearable
|
||||
maxlength="16" show-word-limit />
|
||||
<div class="text-sm text-gray-400">{{ t('pageTitleTips') }}</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<!-- 表单布局 页面设置 -->
|
||||
<slot name="content"></slot>
|
||||
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('statusBarContent') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]" @submit.prevent>
|
||||
<el-form-item :label="t('topStatusBarNav')" class="display-block">
|
||||
<el-switch v-model="diyStore.global.topStatusBar.isShow"/>
|
||||
<div class="text-sm text-gray-400">{{ t('statusBarSwitchTips') }}</div>
|
||||
</el-form-item>
|
||||
<el-switch v-model="diyStore.global.topStatusBar.isShow" />
|
||||
<div class="text-sm text-gray-400">{{ t('statusBarSwitchTips') }}</div>
|
||||
</el-form-item>
|
||||
<template v-if="diyStore.global.topStatusBar.isShow">
|
||||
<el-form-item :label="t('diyTitle')">
|
||||
<el-input v-model.trim="diyStore.global.title" :placeholder="t('diyTitlePlaceholder')" clearable maxlength="12" show-word-limit/>
|
||||
<el-input v-model.trim="diyStore.global.title" :placeholder="t('diyTitlePlaceholder')" clearable maxlength="12" show-word-limit />
|
||||
<div class="text-sm text-gray-400">{{ t('titleTips') }}</div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('selectStyle')" class="display-block">
|
||||
<div class="flex">
|
||||
<span class="text-primary flex-1 cursor-pointer" @click="showStyle">{{diyStore.global.topStatusBar.styleName}}</span>
|
||||
<span class="text-primary flex-1 cursor-pointer" @click="showStyle">{{ diyStore.global.topStatusBar.styleName }}</span>
|
||||
<el-icon>
|
||||
<ArrowRight />
|
||||
</el-icon>
|
||||
@ -41,7 +42,7 @@
|
||||
<div class="text-sm text-gray-400 mt-[10px]">{{ t('topStatusBarImgTips') }}</div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('topStatusBarSearchName')" v-if="'style-3' == diyStore.global.topStatusBar.style">
|
||||
<el-input v-model.trim="diyStore.global.topStatusBar.inputPlaceholder" :placeholder="t('topStatusBarSearchNamePlaceholder')" clearable maxlength="12" show-word-limit/>
|
||||
<el-input v-model.trim="diyStore.global.topStatusBar.inputPlaceholder" :placeholder="t('topStatusBarSearchNamePlaceholder')" clearable maxlength="12" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('textAlign')" v-show="diyStore.global.topStatusBar.style == 'style-1'">
|
||||
<el-radio-group v-model="diyStore.global.topStatusBar.textAlign">
|
||||
@ -53,31 +54,35 @@
|
||||
<diy-link v-model="diyStore.global.topStatusBar.link" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-form>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('bottomNavContent') }}</h3>
|
||||
<h3 class="mb-[10px]">{{ t('bottomNavContent') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('tabbar')" class="display-block">
|
||||
<el-switch v-model="diyStore.global.bottomTabBarSwitch"/>
|
||||
<div class="text-sm text-gray-400">{{ t('tabbarSwitchTips') }}</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<el-form-item :label="t('tabbar')" class="display-block">
|
||||
<el-switch v-model="diyStore.global.bottomTabBarSwitch" />
|
||||
<div class="text-sm text-gray-400">{{ t('tabbarSwitchTips') }}</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<el-dialog v-model="showDialog" :title="t('selectStyle')" width="800px">
|
||||
<el-dialog v-model="showDialog" :title="t('selectStyle')" width="800px">
|
||||
|
||||
<div class="flex flex-wrap">
|
||||
<div class="flex items-center justify-center overflow-hidden w-[32%] h-[100px] mr-[2%] mb-[15px] cursor-pointer border bg-gray-50" :class="{ 'border-primary': selectStyle == 'style-1' }" @click="selectStyle = 'style-1'">
|
||||
<div class="flex items-center justify-center overflow-hidden w-[32%] h-[100px] mr-[2%] mb-[15px] cursor-pointer border bg-gray-50"
|
||||
:class="{ 'border-primary': selectStyle == 'style-1' }" @click="selectStyle = 'style-1'">
|
||||
<img class="max-w-[100%] max-h-[100%]" src="@/app/assets/images/diy/head/nav_style1.jpg" />
|
||||
</div>
|
||||
<div class="flex items-center justify-center overflow-hidden w-[32%] h-[100px] mr-[2%] mb-[15px] cursor-pointer border bg-gray-50" :class="{ 'border-primary': selectStyle == 'style-2' }" @click="selectStyle = 'style-2'">
|
||||
<div class="flex items-center justify-center overflow-hidden w-[32%] h-[100px] mr-[2%] mb-[15px] cursor-pointer border bg-gray-50"
|
||||
:class="{ 'border-primary': selectStyle == 'style-2' }" @click="selectStyle = 'style-2'">
|
||||
<img class="max-w-[100%] max-h-[100%]" src="@/app/assets/images/diy/head/nav_style2.jpg" />
|
||||
</div>
|
||||
<div class="flex items-center justify-center overflow-hidden w-[32%] h-[100px] mb-[15px] cursor-pointer border bg-gray-50" :class="{ 'border-primary': selectStyle == 'style-3' }" @click="selectStyle = 'style-3'">
|
||||
<div class="flex items-center justify-center overflow-hidden w-[32%] h-[100px] mb-[15px] cursor-pointer border bg-gray-50"
|
||||
:class="{ 'border-primary': selectStyle == 'style-3' }" @click="selectStyle = 'style-3'">
|
||||
<img class="max-w-[100%] max-h-[100%]" src="@/app/assets/images/diy/head/nav_style3.jpg" />
|
||||
</div>
|
||||
<div class="flex items-center justify-center overflow-hidden w-[32%] h-[100px] mr-[2%] cursor-pointer border bg-gray-50" :class="{ 'border-primary': selectStyle == 'style-4' }" @click="selectStyle = 'style-4'">
|
||||
<div class="flex items-center justify-center overflow-hidden w-[32%] h-[100px] mr-[2%] cursor-pointer border bg-gray-50"
|
||||
:class="{ 'border-primary': selectStyle == 'style-4' }" @click="selectStyle = 'style-4'">
|
||||
<img class="max-w-[100%] max-h-[100%]" src="@/app/assets/images/diy/head/nav_style4.jpg" />
|
||||
</div>
|
||||
</div>
|
||||
@ -90,59 +95,59 @@
|
||||
</template>
|
||||
|
||||
</el-dialog>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('pageStyle') }}</h3>
|
||||
<el-form label-width="115px" class="px-[10px]">
|
||||
<el-form-item :label="t('pageBgColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.pageStartBgColor" show-alpha :predefine="diyStore.predefineColors" />
|
||||
<icon name="iconfont iconmap-connect" size="20px" class="block !text-gray-400 mx-[5px]"/>
|
||||
<el-color-picker v-model="diyStore.editComponent.pageEndBgColor" show-alpha :predefine="diyStore.predefineColors" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('bgGradientAngle')">
|
||||
<el-radio-group v-model="diyStore.editComponent.pageGradientAngle">
|
||||
<el-radio label="to bottom">{{ t('topToBottom') }}</el-radio>
|
||||
<el-radio label="to right">{{ t('leftToRight') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('bgHeightScale')">
|
||||
<el-slider v-model="diyStore.global.bgHeightScale" show-input size="small" class="ml-[10px] diy-nav-slider"/>
|
||||
</el-form-item>
|
||||
<div class="text-sm text-gray-400 ml-[80px] mb-[10px]">{{ t('bgHeightScaleTip') }}</div>
|
||||
<el-form-item :label="t('bgUrl')">
|
||||
<upload-image v-model="diyStore.global.bgUrl" :limit="1"/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('statusBarStyle') }}</h3>
|
||||
<el-form label-width="115px" class="px-[10px]">
|
||||
<h3 class="mb-[10px]">{{ t('pageStyle') }}</h3>
|
||||
<el-form label-width="115px" class="px-[10px]">
|
||||
<el-form-item :label="t('pageBgColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.pageStartBgColor" show-alpha :predefine="diyStore.predefineColors" />
|
||||
<icon name="iconfont iconmap-connect" size="20px" class="block !text-gray-400 mx-[5px]" />
|
||||
<el-color-picker v-model="diyStore.editComponent.pageEndBgColor" show-alpha :predefine="diyStore.predefineColors" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('bgGradientAngle')">
|
||||
<el-radio-group v-model="diyStore.editComponent.pageGradientAngle">
|
||||
<el-radio label="to bottom">{{ t('topToBottom') }}</el-radio>
|
||||
<el-radio label="to right">{{ t('leftToRight') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('bgHeightScale')">
|
||||
<el-slider v-model="diyStore.global.bgHeightScale" show-input size="small" class="ml-[10px] diy-nav-slider" />
|
||||
</el-form-item>
|
||||
<div class="text-sm text-gray-400 ml-[80px] mb-[10px]">{{ t('bgHeightScaleTip') }}</div>
|
||||
<el-form-item :label="t('bgUrl')">
|
||||
<upload-image v-model="diyStore.global.bgUrl" :limit="1" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('statusBarStyle') }}</h3>
|
||||
<el-form label-width="115px" class="px-[10px]">
|
||||
<el-form-item :label="t('topStatusBarBgColor')" class="display-block">
|
||||
<el-color-picker v-model="diyStore.global.topStatusBar.bgColor" show-alpha />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('rollTopStatusBarBgColor')" class="display-block">
|
||||
<el-color-picker v-model="diyStore.global.topStatusBar.rollBgColor" show-alpha />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('topStatusBarTextColor')" class="display-block">
|
||||
<el-color-picker v-model="diyStore.global.topStatusBar.textColor" show-alpha />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('rollTopStatusBarTextColor')" class="display-block">
|
||||
<el-color-picker v-model="diyStore.global.topStatusBar.rollTextColor" show-alpha />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('marginSet') }}</h3>
|
||||
<el-form label-width="115px" class="px-[10px]">
|
||||
<el-form-item :label="t('marginBoth')">
|
||||
<el-slider v-model="diyStore.global.template.margin.both" show-input size="small" @input="inputBoth" class="ml-[10px] diy-nav-slider"/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
<el-color-picker v-model="diyStore.global.topStatusBar.bgColor" show-alpha />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('rollTopStatusBarBgColor')" class="display-block">
|
||||
<el-color-picker v-model="diyStore.global.topStatusBar.rollBgColor" show-alpha />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('topStatusBarTextColor')" class="display-block">
|
||||
<el-color-picker v-model="diyStore.global.topStatusBar.textColor" show-alpha />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('rollTopStatusBarTextColor')" class="display-block">
|
||||
<el-color-picker v-model="diyStore.global.topStatusBar.rollTextColor" show-alpha />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('marginSet') }}</h3>
|
||||
<el-form label-width="115px" class="px-[10px]">
|
||||
<el-form-item :label="t('marginBoth')">
|
||||
<el-slider v-model="diyStore.global.template.margin.both" show-input size="small" @input="inputBoth" class="ml-[10px] diy-nav-slider" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
@ -159,11 +164,11 @@ watch(
|
||||
// 设置图片宽高
|
||||
const image = new Image()
|
||||
image.src = img(diyStore.global.bgUrl)
|
||||
image.onload = async () => {
|
||||
image.onload = async() => {
|
||||
diyStore.global.imgWidth = image.width
|
||||
diyStore.global.imgHeight = image.height
|
||||
}
|
||||
if(!diyStore.global.bgUrl){
|
||||
if (!diyStore.global.bgUrl) {
|
||||
diyStore.global.imgWidth = ''
|
||||
diyStore.global.imgHeight = ''
|
||||
}
|
||||
@ -171,8 +176,8 @@ watch(
|
||||
)
|
||||
|
||||
// 改变页面的左右边距时,更新所有组件的数值
|
||||
const inputBoth = (value:any)=>{
|
||||
diyStore.value.forEach((item,index)=>{
|
||||
const inputBoth = (value: any) => {
|
||||
diyStore.value.forEach((item, index) => {
|
||||
item.margin.both = value;
|
||||
})
|
||||
|
||||
@ -192,7 +197,7 @@ const showStyle = () => {
|
||||
|
||||
const selectStyle = ref("style-1")
|
||||
const changeStyle = () => {
|
||||
switch (selectStyle.value) {
|
||||
switch (selectStyle.value) {
|
||||
case 'style-1':
|
||||
diyStore.global.topStatusBar.styleName = '风格1'
|
||||
break
|
||||
|
||||
@ -1,127 +1,129 @@
|
||||
<template>
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('pictureShowBlockOne') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('image')">
|
||||
<upload-image v-model="diyStore.editComponent.moduleOne.head.textImg" :limit="1"/>
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('pictureShowBlockOne') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('image')">
|
||||
<upload-image v-model="diyStore.editComponent.moduleOne.head.textImg" :limit="1" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('subTitle')">
|
||||
<el-input v-model.trim="diyStore.editComponent.moduleOne.head.subText" :placeholder="t('subTitlePlaceholder')" clearable maxlength="8" show-word-limit />
|
||||
<el-input v-model.trim="diyStore.editComponent.moduleOne.head.subText"
|
||||
:placeholder="t('subTitlePlaceholder')" clearable maxlength="8" show-word-limit />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('subTitleTextColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.moduleOne.head.subTextColor" show-alpha />
|
||||
<el-color-picker v-model="diyStore.editComponent.moduleOne.head.subTextColor" show-alpha />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('pictureShowBgColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.moduleOne.listFrame.startColor" show-alpha />
|
||||
<icon name="iconfont iconmap-connect" size="20px" class="block !text-gray-400 mx-[5px]"/>
|
||||
<el-color-picker v-model="diyStore.editComponent.moduleOne.listFrame.startColor" show-alpha />
|
||||
<icon name="iconfont iconmap-connect" size="20px" class="block !text-gray-400 mx-[5px]" />
|
||||
<el-color-picker v-model="diyStore.editComponent.moduleOne.listFrame.endColor" show-alpha />
|
||||
</el-form-item>
|
||||
|
||||
<div v-for="(item,index) in diyStore.editComponent.moduleOne.list" :key="item.id" class="item-wrap p-[10px] pb-0 relative border border-dashed border-gray-300 mb-[16px]">
|
||||
<div v-for="(item,index) in diyStore.editComponent.moduleOne.list" :key="item.id"
|
||||
class="item-wrap p-[10px] pb-0 relative border border-dashed border-gray-300 mb-[16px]">
|
||||
<el-form-item :label="t('image')">
|
||||
<upload-image v-model="item.imageUrl" :limit="1"/>
|
||||
<upload-image v-model="item.imageUrl" :limit="1" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('pictureShowBtnText')">
|
||||
<el-input v-model.trim="item.btnTitle.text" :placeholder="t('activeCubeTitlePlaceholder')" clearable maxlength="4" show-word-limit/>
|
||||
<el-input v-model.trim="item.btnTitle.text" :placeholder="t('activeCubeTitlePlaceholder')" clearable maxlength="4" show-word-limit />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('pictureShowBtnColor')">
|
||||
<el-color-picker v-model="item.btnTitle.color" show-alpha />
|
||||
<el-color-picker v-model="item.btnTitle.color" show-alpha />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('pictureShowBtnBgColor')">
|
||||
<el-color-picker v-model="item.btnTitle.startColor" show-alpha />
|
||||
<icon name="iconfont iconmap-connect" size="20px" class="block !text-gray-400 mx-[5px]"/>
|
||||
<el-color-picker v-model="item.btnTitle.startColor" show-alpha />
|
||||
<icon name="iconfont iconmap-connect" size="20px" class="block !text-gray-400 mx-[5px]" />
|
||||
<el-color-picker v-model="item.btnTitle.endColor" show-alpha />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('link')">
|
||||
<diy-link v-model="item.link"/>
|
||||
<diy-link v-model="item.link" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('pictureShowBlockTwo') }}</h3>
|
||||
<el-form label-width="90px" class="px-[10px]">
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('pictureShowBlockTwo') }}</h3>
|
||||
<el-form label-width="90px" class="px-[10px]">
|
||||
<el-form-item :label="t('image')">
|
||||
<upload-image v-model="diyStore.editComponent.moduleTwo.head.textImg" :limit="1"/>
|
||||
<upload-image v-model="diyStore.editComponent.moduleTwo.head.textImg" :limit="1" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('subTitle')">
|
||||
<el-input v-model.trim="diyStore.editComponent.moduleTwo.head.subText" :placeholder="t('subTitlePlaceholder')" clearable maxlength="8" show-word-limit />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('subTitleTextColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.moduleTwo.head.subTextColor" show-alpha />
|
||||
<el-color-picker v-model="diyStore.editComponent.moduleTwo.head.subTextColor" show-alpha />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('pictureShowBgColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.moduleTwo.listFrame.startColor" show-alpha />
|
||||
<icon name="iconfont iconmap-connect" size="20px" class="block !text-gray-400 mx-[5px]"/>
|
||||
<el-color-picker v-model="diyStore.editComponent.moduleTwo.listFrame.startColor" show-alpha />
|
||||
<icon name="iconfont iconmap-connect" size="20px" class="block !text-gray-400 mx-[5px]" />
|
||||
<el-color-picker v-model="diyStore.editComponent.moduleTwo.listFrame.endColor" show-alpha />
|
||||
</el-form-item>
|
||||
|
||||
<div v-for="(item,index) in diyStore.editComponent.moduleTwo.list" :key="item.id" class="item-wrap p-[10px] pb-0 relative border border-dashed border-gray-300 mb-[16px]">
|
||||
<div v-for="(item,index) in diyStore.editComponent.moduleTwo.list" :key="item.id"
|
||||
class="item-wrap p-[10px] pb-0 relative border border-dashed border-gray-300 mb-[16px]">
|
||||
<el-form-item :label="t('image')">
|
||||
<upload-image v-model="item.imageUrl" :limit="1"/>
|
||||
<upload-image v-model="item.imageUrl" :limit="1" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('pictureShowBtnText')">
|
||||
<el-input v-model.trim="item.btnTitle.text" :placeholder="t('activeCubeTitlePlaceholder')" clearable maxlength="4" show-word-limit/>
|
||||
<el-input v-model.trim="item.btnTitle.text" :placeholder="t('activeCubeTitlePlaceholder')" clearable maxlength="4" show-word-limit />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('pictureShowBtnColor')">
|
||||
<el-color-picker v-model="item.btnTitle.color" show-alpha />
|
||||
<el-color-picker v-model="item.btnTitle.color" show-alpha />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('pictureShowBtnBgColor')">
|
||||
<el-color-picker v-model="item.btnTitle.startColor" show-alpha />
|
||||
<icon name="iconfont iconmap-connect" size="20px" class="block !text-gray-400 mx-[5px]"/>
|
||||
<el-color-picker v-model="item.btnTitle.startColor" show-alpha />
|
||||
<icon name="iconfont iconmap-connect" size="20px" class="block !text-gray-400 mx-[5px]" />
|
||||
<el-color-picker v-model="item.btnTitle.endColor" show-alpha />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('link')">
|
||||
<diy-link v-model="item.link"/>
|
||||
<diy-link v-model="item.link" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
</el-form>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('pictureShowBlockStyle') }}</h3>
|
||||
<el-form label-width="90px" class="px-[10px]">
|
||||
<el-form-item :label="t('topRounded')">
|
||||
<el-slider v-model="diyStore.editComponent.moduleRounded.topRounded" show-input size="small" class="ml-[10px] diy-nav-slider" :max="100"/>
|
||||
<h3 class="mb-[10px]">{{ t('pictureShowBlockStyle') }}</h3>
|
||||
<el-form label-width="90px" class="px-[10px]">
|
||||
<el-form-item :label="t('topRounded')">
|
||||
<el-slider v-model="diyStore.editComponent.moduleRounded.topRounded" show-input size="small" class="ml-[10px] diy-nav-slider" :max="100" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('bottomRounded')">
|
||||
<el-slider v-model="diyStore.editComponent.moduleRounded.bottomRounded" show-input size="small" class="ml-[10px] diy-nav-slider" :max="100"/>
|
||||
<el-slider v-model="diyStore.editComponent.moduleRounded.bottomRounded" show-input size="small" class="ml-[10px] diy-nav-slider" :max="100" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
</div>
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { t } from '@/lang'
|
||||
import useDiyStore from '@/stores/modules/diy'
|
||||
import { img } from '@/utils/common'
|
||||
import { ref, reactive } from 'vue'
|
||||
|
||||
const diyStore = useDiyStore()
|
||||
|
||||
@ -1,18 +1,18 @@
|
||||
<template>
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('richTextContentSet') }}</h3>
|
||||
<editor v-model="diyStore.editComponent.html" :height="600" class="editor-width" />
|
||||
</div>
|
||||
</div>
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('richTextContentSet') }}</h3>
|
||||
<editor v-model="diyStore.editComponent.html" :height="600" class="editor-width" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
</div>
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
@ -27,7 +27,7 @@ diyStore.editComponent.ignore = [] // 忽略公共属性
|
||||
diyStore.editComponent.verify = (index: number) => {
|
||||
const res = { code: true, message: '' }
|
||||
|
||||
if(diyStore.value[index].html == '<p><br></p>'){
|
||||
if (diyStore.value[index].html == '<p><br></p>') {
|
||||
res.code = false
|
||||
res.message = t('richTextPlaceholder')
|
||||
return res
|
||||
|
||||
@ -1,73 +1,75 @@
|
||||
<template>
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap rubik-cube" v-show="diyStore.editTab == 'content'">
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap rubik-cube" v-show="diyStore.editTab == 'content'">
|
||||
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('selectStyle') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('template')">
|
||||
<span>{{ selectTemplate.name }}</span>
|
||||
</el-form-item>
|
||||
<ul class="selected-template-list">
|
||||
<li v-for="(item,i) in templateList" :key="i" :class="[(item.className == diyStore.editComponent.mode) ? 'selected' : '' ]" @click="changeTemplateList(i)">
|
||||
<icon :name="'iconfont ' + item.src" size="16px"/>
|
||||
</li>
|
||||
</ul>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('rubikCubeLayout') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('selectStyle') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('template')">
|
||||
<span>{{ selectTemplate.name }}</span>
|
||||
</el-form-item>
|
||||
<ul class="selected-template-list">
|
||||
<li v-for="(item,i) in templateList" :key="i"
|
||||
:class="[(item.className == diyStore.editComponent.mode) ? 'selected' : '' ]"
|
||||
@click="changeTemplateList(i)">
|
||||
<icon :name="'iconfont ' + item.src" size="16px" />
|
||||
</li>
|
||||
</ul>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('rubikCubeLayout') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
|
||||
<ul class="layout">
|
||||
<li v-for="(li,i) in selectTemplate.dimensionScale" :key="i" :class="[selectTemplate.className]">
|
||||
<div class="have-preview-image" v-show="diyStore.editComponent.list[i].imageUrl && diyStore.editComponent.list[i].imageUrl != 'static/resource/images/diy/figure.png'">
|
||||
<img :src="img(diyStore.editComponent.list[i].imageUrl)"/>
|
||||
</div>
|
||||
<div class="empty" :class="[selectTemplate.className]" v-show="!diyStore.editComponent.list[i].imageUrl || diyStore.editComponent.list[i].imageUrl == 'static/resource/images/diy/figure.png'">
|
||||
<p>{{li.name}}</p>
|
||||
<p>{{li.desc}}</p>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="layout">
|
||||
<li v-for="(li,i) in selectTemplate.dimensionScale" :key="i" :class="[selectTemplate.className]">
|
||||
<div class="have-preview-image" v-show="diyStore.editComponent.list[i].imageUrl && diyStore.editComponent.list[i].imageUrl != 'static/resource/images/diy/figure.png'">
|
||||
<img :src="img(diyStore.editComponent.list[i].imageUrl)" />
|
||||
</div>
|
||||
<div class="empty" :class="[selectTemplate.className]" v-show="!diyStore.editComponent.list[i].imageUrl || diyStore.editComponent.list[i].imageUrl == 'static/resource/images/diy/figure.png'">
|
||||
<p>{{ li.name }}</p>
|
||||
<p>{{ li.desc }}</p>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div v-for="(item) in diyStore.editComponent.list" :key="item.id" class="item-wrap p-[10px] pb-0 relative border border-dashed border-gray-300 mb-[16px]">
|
||||
<el-form-item :label="t('image')">
|
||||
<upload-image v-model="item.imageUrl" :limit="1" @change="selectImg"/>
|
||||
</el-form-item>
|
||||
<div v-for="(item) in diyStore.editComponent.list" :key="item.id" class="item-wrap p-[10px] pb-0 relative border border-dashed border-gray-300 mb-[16px]">
|
||||
<el-form-item :label="t('image')">
|
||||
<upload-image v-model="item.imageUrl" :limit="1" @change="selectImg" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('link')">
|
||||
<diy-link v-model="item.link"/>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<el-form-item :label="t('link')">
|
||||
<diy-link v-model="item.link" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
</el-form>
|
||||
</el-form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('rubikCubeStyle') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('imageGap')">
|
||||
<el-slider v-model="diyStore.editComponent.imageGap" show-input size="small" class="ml-[10px] diy-nav-slider" :max="30"/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('topRounded')">
|
||||
<el-slider v-model="diyStore.editComponent.topElementRounded" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50"/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('bottomRounded')">
|
||||
<el-slider v-model="diyStore.editComponent.bottomElementRounded" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50"/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('rubikCubeStyle') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('imageGap')">
|
||||
<el-slider v-model="diyStore.editComponent.imageGap" show-input size="small" class="ml-[10px] diy-nav-slider" :max="30" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('topRounded')">
|
||||
<el-slider v-model="diyStore.editComponent.topElementRounded" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('bottomRounded')">
|
||||
<el-slider v-model="diyStore.editComponent.bottomElementRounded" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
</div>
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
@ -312,16 +314,16 @@ const changeTemplateList = (v: number) => {
|
||||
}
|
||||
}
|
||||
|
||||
const selectImg = (url:string) => {
|
||||
const selectImg = (url: string) => {
|
||||
handleHeight(true)
|
||||
}
|
||||
|
||||
// 处理高度
|
||||
const handleHeight = (isCalcHeight:boolean = false) => {
|
||||
const handleHeight = (isCalcHeight: boolean = false) => {
|
||||
diyStore.editComponent.list.forEach((item: any, index: number) => {
|
||||
const image = new Image()
|
||||
image.src = img(item.imageUrl)
|
||||
image.onload = async () => {
|
||||
image.onload = async() => {
|
||||
item.imgWidth = image.width
|
||||
item.imgHeight = image.height
|
||||
}
|
||||
@ -332,307 +334,307 @@ defineExpose({})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.rubik-cube .selected-template-list {
|
||||
/*padding-left: 15px;*/
|
||||
margin-bottom: 20px;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
.rubik-cube .selected-template-list {
|
||||
/*padding-left: 15px;*/
|
||||
margin-bottom: 20px;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
li {
|
||||
color: #909399;
|
||||
width: 46px;
|
||||
height: 32px;
|
||||
text-align: center;
|
||||
line-height: 29px;
|
||||
border: 1px solid #e5e5e5;
|
||||
cursor: pointer;
|
||||
background: #ffffff;
|
||||
box-sizing: border-box;
|
||||
border-right: 1px transparent solid;
|
||||
li {
|
||||
color: #909399;
|
||||
width: 46px;
|
||||
height: 32px;
|
||||
text-align: center;
|
||||
line-height: 29px;
|
||||
border: 1px solid #e5e5e5;
|
||||
cursor: pointer;
|
||||
background: #ffffff;
|
||||
box-sizing: border-box;
|
||||
border-right: 1px transparent solid;
|
||||
|
||||
&:last-child {
|
||||
border-right: 1px solid #e5e5e5;
|
||||
}
|
||||
&:last-child {
|
||||
border-right: 1px solid #e5e5e5;
|
||||
}
|
||||
|
||||
&.selected {
|
||||
color: var(--el-color-primary);
|
||||
border-color: var(--el-color-primary);
|
||||
}
|
||||
&.selected {
|
||||
color: var(--el-color-primary);
|
||||
border-color: var(--el-color-primary);
|
||||
}
|
||||
|
||||
img {
|
||||
display: inline-block;
|
||||
}
|
||||
img {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
div {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
div {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.layout {
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
margin-bottom: 15px;
|
||||
.layout {
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
margin-bottom: 15px;
|
||||
|
||||
li {
|
||||
float: left;
|
||||
color: #909399;
|
||||
border: 1px solid #e5e5e5;
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
position: relative;
|
||||
li {
|
||||
float: left;
|
||||
color: #909399;
|
||||
border: 1px solid #e5e5e5;
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
position: relative;
|
||||
|
||||
div.empty {
|
||||
left: 0;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
margin-top: -26px;
|
||||
div.empty {
|
||||
left: 0;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
margin-top: -26px;
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
line-height: 26px;
|
||||
}
|
||||
}
|
||||
p {
|
||||
margin: 0;
|
||||
line-height: 26px;
|
||||
}
|
||||
}
|
||||
|
||||
div.have-preview-image {
|
||||
box-sizing: border-box;
|
||||
div.have-preview-image {
|
||||
box-sizing: border-box;
|
||||
|
||||
img {
|
||||
display: inline-block;
|
||||
width: auto;
|
||||
height: auto;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
}
|
||||
}
|
||||
img {
|
||||
display: inline-block;
|
||||
width: auto;
|
||||
height: auto;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
// 1行2个
|
||||
&.row1-of2 {
|
||||
width: 49.2%;
|
||||
height: 160px;
|
||||
border-right: 1px transparent solid;
|
||||
// 1行2个
|
||||
&.row1-of2 {
|
||||
width: 49.2%;
|
||||
height: 160px;
|
||||
border-right: 1px transparent solid;
|
||||
|
||||
&:last-child {
|
||||
border-right: 1px solid #e5e5e5;
|
||||
}
|
||||
&:last-child {
|
||||
border-right: 1px solid #e5e5e5;
|
||||
}
|
||||
|
||||
div.empty {
|
||||
}
|
||||
div.empty {
|
||||
}
|
||||
|
||||
div.have-preview-image {
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
line-height: 160px;
|
||||
background: #ffffff;
|
||||
}
|
||||
div.have-preview-image {
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
line-height: 160px;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// 1行3个
|
||||
&.row1-of3 {
|
||||
width: 32.5%;
|
||||
height: 100px;
|
||||
border-right: 1px transparent solid;
|
||||
// 1行3个
|
||||
&.row1-of3 {
|
||||
width: 32.5%;
|
||||
height: 100px;
|
||||
border-right: 1px transparent solid;
|
||||
|
||||
&:last-child {
|
||||
border-right: 1px solid #bdf;
|
||||
}
|
||||
&:last-child {
|
||||
border-right: 1px solid #bdf;
|
||||
}
|
||||
|
||||
div.empty {
|
||||
}
|
||||
div.empty {
|
||||
}
|
||||
|
||||
div.have-preview-image {
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
line-height: 100px;
|
||||
background: #ffffff;
|
||||
}
|
||||
}
|
||||
div.have-preview-image {
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
line-height: 100px;
|
||||
background: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
// 1行4个
|
||||
&.row1-of4 {
|
||||
width: 24.2%;
|
||||
height: 80px;
|
||||
border-right: 1px transparent solid;
|
||||
// 1行4个
|
||||
&.row1-of4 {
|
||||
width: 24.2%;
|
||||
height: 80px;
|
||||
border-right: 1px transparent solid;
|
||||
|
||||
&:last-child {
|
||||
border-right: 1px solid #bdf;
|
||||
}
|
||||
&:last-child {
|
||||
border-right: 1px solid #bdf;
|
||||
}
|
||||
|
||||
div.empty {
|
||||
}
|
||||
div.empty {
|
||||
}
|
||||
|
||||
div.have-preview-image {
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
line-height: 80px;
|
||||
background: #ffffff;
|
||||
}
|
||||
}
|
||||
div.have-preview-image {
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
line-height: 80px;
|
||||
background: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
// 2左2右
|
||||
&.row2-lt-of2-rt {
|
||||
width: 49.2%;
|
||||
height: 160px;
|
||||
// 2左2右
|
||||
&.row2-lt-of2-rt {
|
||||
width: 49.2%;
|
||||
height: 160px;
|
||||
|
||||
&:nth-child(1) {
|
||||
border-right: 1px transparent solid;
|
||||
border-bottom: 1px transparent solid;
|
||||
}
|
||||
&:nth-child(1) {
|
||||
border-right: 1px transparent solid;
|
||||
border-bottom: 1px transparent solid;
|
||||
}
|
||||
|
||||
&:nth-child(2) {
|
||||
border-bottom: 1px transparent solid;
|
||||
}
|
||||
&:nth-child(2) {
|
||||
border-bottom: 1px transparent solid;
|
||||
}
|
||||
|
||||
&:nth-child(3) {
|
||||
border-right: 1px transparent solid;
|
||||
clear: both;
|
||||
}
|
||||
&:nth-child(3) {
|
||||
border-right: 1px transparent solid;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
div.empty {
|
||||
}
|
||||
div.empty {
|
||||
}
|
||||
|
||||
div.have-preview-image {
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
line-height: 160px;
|
||||
background: #ffffff;
|
||||
}
|
||||
}
|
||||
div.have-preview-image {
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
line-height: 160px;
|
||||
background: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
// 1左2右
|
||||
&.row1-lt-of2-rt {
|
||||
width: 49.2%;
|
||||
font-size: 12px;
|
||||
// 1左2右
|
||||
&.row1-lt-of2-rt {
|
||||
width: 49.2%;
|
||||
font-size: 12px;
|
||||
|
||||
&:nth-child(1) {
|
||||
height: 322px;
|
||||
border-right: 1px transparent solid;
|
||||
&:nth-child(1) {
|
||||
height: 322px;
|
||||
border-right: 1px transparent solid;
|
||||
|
||||
div.have-preview-image {
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
line-height: 322px;
|
||||
background: #ffffff;
|
||||
}
|
||||
}
|
||||
div.have-preview-image {
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
line-height: 322px;
|
||||
background: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
&:nth-child(2) {
|
||||
height: 160px;
|
||||
border-bottom: 1px transparent solid;
|
||||
&:nth-child(2) {
|
||||
height: 160px;
|
||||
border-bottom: 1px transparent solid;
|
||||
|
||||
div.have-preview-image {
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
line-height: 160px;
|
||||
background: #ffffff;
|
||||
}
|
||||
}
|
||||
div.have-preview-image {
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
line-height: 160px;
|
||||
background: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
&:nth-child(3) {
|
||||
height: 160px;
|
||||
&:nth-child(3) {
|
||||
height: 160px;
|
||||
|
||||
div.have-preview-image {
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
line-height: 160px;
|
||||
background: #ffffff;
|
||||
}
|
||||
}
|
||||
div.have-preview-image {
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
line-height: 160px;
|
||||
background: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
div.empty {
|
||||
}
|
||||
}
|
||||
div.empty {
|
||||
}
|
||||
}
|
||||
|
||||
// 1上2下
|
||||
&.row1-tp-of2-bm {
|
||||
height: 160px;
|
||||
// 1上2下
|
||||
&.row1-tp-of2-bm {
|
||||
height: 160px;
|
||||
|
||||
&:nth-child(1) {
|
||||
width: 99.4%;
|
||||
border-bottom: 1px transparent solid;
|
||||
}
|
||||
&:nth-child(1) {
|
||||
width: 99.4%;
|
||||
border-bottom: 1px transparent solid;
|
||||
}
|
||||
|
||||
&:nth-child(2) {
|
||||
width: 49.2%;
|
||||
border-right: 1px transparent solid;
|
||||
}
|
||||
&:nth-child(2) {
|
||||
width: 49.2%;
|
||||
border-right: 1px transparent solid;
|
||||
}
|
||||
|
||||
&:nth-child(3) {
|
||||
width: 49.2%;
|
||||
}
|
||||
&:nth-child(3) {
|
||||
width: 49.2%;
|
||||
}
|
||||
|
||||
div.empty {
|
||||
}
|
||||
div.empty {
|
||||
}
|
||||
|
||||
div.have-preview-image {
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
line-height: 160px;
|
||||
background: #ffffff;
|
||||
}
|
||||
}
|
||||
div.have-preview-image {
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
line-height: 160px;
|
||||
background: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
// 1左3右
|
||||
&.row1-lt-of1-tp-of2-bm {
|
||||
&:nth-child(1) {
|
||||
height: 320px;
|
||||
width: 49.2%;
|
||||
border-right: 1px transparent solid;
|
||||
// 1左3右
|
||||
&.row1-lt-of1-tp-of2-bm {
|
||||
&:nth-child(1) {
|
||||
height: 320px;
|
||||
width: 49.2%;
|
||||
border-right: 1px transparent solid;
|
||||
|
||||
div.have-preview-image {
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
line-height: 320px;
|
||||
background: #ffffff;
|
||||
}
|
||||
}
|
||||
div.have-preview-image {
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
line-height: 320px;
|
||||
background: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
&:nth-child(2) {
|
||||
height: 160px;
|
||||
width: 49.2%;
|
||||
border-bottom: 1px transparent solid;
|
||||
&:nth-child(2) {
|
||||
height: 160px;
|
||||
width: 49.2%;
|
||||
border-bottom: 1px transparent solid;
|
||||
|
||||
div.have-preview-image {
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
line-height: 160px;
|
||||
background: #ffffff;
|
||||
}
|
||||
}
|
||||
div.have-preview-image {
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
line-height: 160px;
|
||||
background: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
&:nth-child(3) {
|
||||
height: 160px;
|
||||
width: 24.2%;
|
||||
border-right: 1px transparent solid;
|
||||
&:nth-child(3) {
|
||||
height: 160px;
|
||||
width: 24.2%;
|
||||
border-right: 1px transparent solid;
|
||||
|
||||
div.have-preview-image {
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
line-height: 160px;
|
||||
background: #ffffff;
|
||||
}
|
||||
}
|
||||
div.have-preview-image {
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
line-height: 160px;
|
||||
background: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
&:nth-child(4) {
|
||||
height: 160px;
|
||||
width: 24.2%;
|
||||
&:nth-child(4) {
|
||||
height: 160px;
|
||||
width: 24.2%;
|
||||
|
||||
div.have-preview-image {
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
line-height: 160px;
|
||||
background: #ffffff;
|
||||
}
|
||||
}
|
||||
div.have-preview-image {
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
line-height: 160px;
|
||||
background: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
div.empty {
|
||||
}
|
||||
}
|
||||
div.empty {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</style>
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,114 +1,119 @@
|
||||
<template>
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('styleSet') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('selectStyle')" class="flex">
|
||||
<span class="text-primary flex-1 cursor-pointer" @click="showStyle">{{ diyStore.editComponent.styleName }}</span>
|
||||
<el-icon>
|
||||
<ArrowRight />
|
||||
</el-icon>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('titleContent') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('title')">
|
||||
<el-input v-model.trim="diyStore.editComponent.text" :placeholder="t('titlePlaceholder')" clearable maxlength="15" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('link')">
|
||||
<diy-link v-model="diyStore.editComponent.link" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('textAlign')" v-show="diyStore.editComponent.style == 'style-1'">
|
||||
<el-radio-group v-model="diyStore.editComponent.textAlign">
|
||||
<el-radio :label="'left'">{{ t('textAlignLeft') }}</el-radio>
|
||||
<el-radio :label="'center'">{{ t('textAlignCenter') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('styleSet') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('selectStyle')" class="flex">
|
||||
<span class="text-primary flex-1 cursor-pointer"
|
||||
@click="showStyle">{{ diyStore.editComponent.styleName }}</span>
|
||||
<el-icon>
|
||||
<ArrowRight />
|
||||
</el-icon>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('titleContent') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('title')">
|
||||
<el-input v-model.trim="diyStore.editComponent.text" :placeholder="t('titlePlaceholder')" clearable maxlength="15" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('link')">
|
||||
<diy-link v-model="diyStore.editComponent.link" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('textAlign')" v-show="diyStore.editComponent.style == 'style-1'">
|
||||
<el-radio-group v-model="diyStore.editComponent.textAlign">
|
||||
<el-radio :label="'left'">{{ t('textAlignLeft') }}</el-radio>
|
||||
<el-radio :label="'center'">{{ t('textAlignCenter') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<div class="edit-attr-item-wrap" v-show="diyStore.editComponent.subTitle.control">
|
||||
<h3 class="mb-[10px]">{{ t('subTitleContent') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('subTitle')">
|
||||
<el-input v-model.trim="diyStore.editComponent.subTitle.text" :placeholder="t('subTitlePlaceholder')" clearable maxlength="30" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('textFontSize')">
|
||||
<el-slider v-model="diyStore.editComponent.subTitle.fontSize" show-input size="small" class="ml-[10px] diy-nav-slider" :min="12" :max="16" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('textColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.subTitle.color" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="edit-attr-item-wrap" v-show="diyStore.editComponent.subTitle.control">
|
||||
<h3 class="mb-[10px]">{{ t('subTitleContent') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('subTitle')">
|
||||
<el-input v-model.trim="diyStore.editComponent.subTitle.text" :placeholder="t('subTitlePlaceholder')" clearable maxlength="30" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('textFontSize')">
|
||||
<el-slider v-model="diyStore.editComponent.subTitle.fontSize" show-input size="small" class="ml-[10px] diy-nav-slider" :min="12" :max="16" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('textColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.subTitle.color" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<div class="edit-attr-item-wrap" v-show="diyStore.editComponent.more.control">
|
||||
<h3 class="mb-[10px]">{{ t('moreContent') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('more')">
|
||||
<el-input v-model.trim="diyStore.editComponent.more.text" :placeholder="t('morePlaceholder')" clearable maxlength="8" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('link')">
|
||||
<diy-link v-model="diyStore.editComponent.more.link" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('moreIsShow')">
|
||||
<el-switch v-model="diyStore.editComponent.more.isShow" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('textColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.more.color" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="edit-attr-item-wrap" v-show="diyStore.editComponent.more.control">
|
||||
<h3 class="mb-[10px]">{{ t('moreContent') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('more')">
|
||||
<el-input v-model.trim="diyStore.editComponent.more.text" :placeholder="t('morePlaceholder')" clearable maxlength="8" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('link')">
|
||||
<diy-link v-model="diyStore.editComponent.more.link" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('moreIsShow')">
|
||||
<el-switch v-model="diyStore.editComponent.more.isShow" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('textColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.more.color" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<el-dialog v-model="showDialog" :title="t('selectStyle')" width="620px">
|
||||
<el-dialog v-model="showDialog" :title="t('selectStyle')" width="620px">
|
||||
|
||||
<div class="flex flex-wrap">
|
||||
<div class="flex items-center justify-center overflow-hidden w-[280px] h-[100px] mr-[12px] cursor-pointer border bg-gray-50" :class="{ 'border-primary': selectStyle == 'style-1' }" @click="selectStyle = 'style-1'">
|
||||
<img class="max-w-[280px] max-h-[220px]" src="@/app/assets/images/diy/text/style1.png" />
|
||||
</div>
|
||||
<div class="flex items-center justify-center overflow-hidden w-[280px] h-[100px] cursor-pointer border bg-gray-50" :class="{ 'border-primary': selectStyle == 'style-2' }" @click="selectStyle = 'style-2'">
|
||||
<img class="max-w-[280px] max-h-[220px]" src="@/app/assets/images/diy/text/style2.png" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-wrap">
|
||||
<div
|
||||
class="flex items-center justify-center overflow-hidden w-[280px] h-[100px] mr-[12px] cursor-pointer border bg-gray-50"
|
||||
:class="{ 'border-primary': selectStyle == 'style-1' }" @click="selectStyle = 'style-1'">
|
||||
<img class="max-w-[280px] max-h-[220px]" src="@/app/assets/images/diy/text/style1.png" />
|
||||
</div>
|
||||
<div
|
||||
class="flex items-center justify-center overflow-hidden w-[280px] h-[100px] cursor-pointer border bg-gray-50"
|
||||
:class="{ 'border-primary': selectStyle == 'style-2' }" @click="selectStyle = 'style-2'">
|
||||
<img class="max-w-[280px] max-h-[220px]" src="@/app/assets/images/diy/text/style2.png" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="showDialog = false">{{ t('cancel') }}</el-button>
|
||||
<el-button type="primary" @click="changeStyle">{{ t('confirm') }}</el-button>
|
||||
</span>
|
||||
</template>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="showDialog = false">{{ t('cancel') }}</el-button>
|
||||
<el-button type="primary" @click="changeStyle">{{ t('confirm') }}</el-button>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
</el-dialog>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('titleStyle') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('textFontSize')">
|
||||
<el-slider v-model="diyStore.editComponent.fontSize" show-input size="small" class="ml-[10px] diy-nav-slider" :min="12" :max="30" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('textFontWeight')">
|
||||
<el-radio-group v-model="diyStore.editComponent.fontWeight">
|
||||
<el-radio :label="'normal'">{{ t('fontWeightNormal') }}</el-radio>
|
||||
<el-radio :label="'bold'">{{ t('fontWeightBold') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('textColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.textColor" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('titleStyle') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('textFontSize')">
|
||||
<el-slider v-model="diyStore.editComponent.fontSize" show-input size="small" class="ml-[10px] diy-nav-slider" :min="12" :max="30" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('textFontWeight')">
|
||||
<el-radio-group v-model="diyStore.editComponent.fontWeight">
|
||||
<el-radio :label="'normal'">{{ t('fontWeightNormal') }}</el-radio>
|
||||
<el-radio :label="'bold'">{{ t('fontWeightBold') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('textColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.textColor" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
||||
@ -2,8 +2,7 @@
|
||||
<el-dialog v-model="dialogThemeVisible" title="编辑色调" width="850px" align-center destroy-on-close="true">
|
||||
<el-form :model="openData" label-width="150px" :rules="formRules">
|
||||
<el-form-item label="色调名称" prop="title">
|
||||
<el-input v-model="openData.title" placeholder="请输入色调名称" maxlength="15" class="!w-[250px]"
|
||||
:disabled="openData.id != ''" />
|
||||
<el-input v-model="openData.title" placeholder="请输入色调名称" maxlength="15" class="!w-[250px]" :disabled="openData.id != ''" @keydown.enter.native.prevent />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
@ -19,8 +18,7 @@
|
||||
<div class="flex items-center">
|
||||
<el-color-picker v-model="item.value" show-alpha :predefine="diyStore.predefineColors" />
|
||||
<span class="text-primary cursor-pointer text-[14px] ml-[20px]" @click="editThemeFn(item)">编辑</span>
|
||||
<span class="text-primary cursor-pointer text-[14px] ml-[8px]"
|
||||
@click="deleteThemeFn(item)">删除</span>
|
||||
<span class="text-primary cursor-pointer text-[14px] ml-[8px]" @click="deleteThemeFn(item)">删除</span>
|
||||
</div>
|
||||
<div class="form-tip">{{ item.tip }}</div>
|
||||
</el-form-item>
|
||||
@ -45,15 +43,15 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed, watch } from 'vue'
|
||||
import { ref, reactive, computed } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { deepClone, filterNumber } from '@/utils/common'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import addThemeComponent from './add-theme.vue'
|
||||
import useDiyStore from '@/stores/modules/diy'
|
||||
import { deleteTheme, addTheme, editTheme } from '@/app/api/diy'
|
||||
import { addTheme, editTheme } from '@/app/api/diy'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
|
||||
const diyStore = useDiyStore()
|
||||
|
||||
const dialogThemeVisible = ref(false)
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<el-dialog v-model="dialogThemeVisible" :title="dialogTitle" width="535px" align-center class="custom-theme-dialog" @close="cancelFn">
|
||||
<div class="flex flex-col items-baseline">
|
||||
<div class="flex items-center flex-wrap max-h-[365px] overflow-auto [&>:nth-child(3n)]:mr-0" >
|
||||
<div class="flex items-center flex-wrap max-h-[365px] overflow-auto [&>:nth-child(3n)]:mr-0">
|
||||
<div :key="tempIndex" v-for="(tempItem, tempIndex) in themeTemp"
|
||||
class="flex flex-col border-[1px] border-solid border-[#dcdee2] rounded-[4px] px-[10px] pt-[10px] pb-[15px] mr-[10px] cursor-pointer my-[5px]"
|
||||
:class="{ '!border-[var(--el-color-primary)]': currTheme.id == tempItem.id }"
|
||||
@click="themeTempChange(tempItem)">
|
||||
class="flex flex-col border-[1px] border-solid border-[#dcdee2] rounded-[4px] px-[10px] pt-[10px] pb-[15px] mr-[10px] cursor-pointer my-[5px]"
|
||||
:class="{ '!border-[var(--el-color-primary)]': currTheme.id == tempItem.id }"
|
||||
@click="themeTempChange(tempItem)">
|
||||
<div class="flex justify-between pb-[5px]">
|
||||
<div class="text-[14px] text-[#666] max-w-[85px] whitespace-nowrap overflow-hidden text-ellipsis" :class="{ '!text-[#333]': currTheme.id == tempItem.id }">{{ tempItem.title }}</div>
|
||||
<div>
|
||||
@ -14,7 +14,8 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<div class="w-[70px] h-[54px] pl-[7px] pt-[9px] flex flex-col mr-[4px] rounded-[4px] text-[10px] leading-[1] text-[#fff]" :style="{ backgroundColor: tempItem.theme['--primary-color'] }">
|
||||
<div class="w-[70px] h-[54px] pl-[7px] pt-[9px] flex flex-col mr-[4px] rounded-[4px] text-[10px] leading-[1] text-[#fff]"
|
||||
:style="{ backgroundColor: tempItem.theme['--primary-color'] }">
|
||||
<span>主色调</span>
|
||||
</div>
|
||||
<div class="flex flex-col">
|
||||
@ -43,14 +44,11 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed, watch } from 'vue'
|
||||
import { ref, reactive, computed } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { setDiyTheme, getDefaultTheme, deleteTheme } from '@/app/api/diy'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import editTheme from './edit-theme.vue'
|
||||
import useDiyStore from '@/stores/modules/diy'
|
||||
import { time } from 'echarts'
|
||||
const diyStore = useDiyStore()
|
||||
|
||||
const editThemeRef = ref()
|
||||
const dialogThemeVisible = ref(false)
|
||||
@ -90,7 +88,7 @@ const open = (res: any) => {
|
||||
}
|
||||
|
||||
const dialogTitle = computed(() => {
|
||||
const name = `选择${currTheme.addon_title}配色`
|
||||
const name = `选择${ currTheme.addon_title }配色`
|
||||
return name
|
||||
})
|
||||
|
||||
@ -190,7 +188,7 @@ defineExpose({
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.secod-color-item {
|
||||
@apply w-[60px] h-[25px] flex flex-col rounded-[4px] text-[10px] text-[#fff] leading-[1] items-end pt-[8px] pr-[7px];
|
||||
}
|
||||
.secod-color-item {
|
||||
@apply w-[60px] h-[25px] flex flex-col rounded-[4px] text-[10px] text-[#fff] leading-[1] items-end pt-[8px] pr-[7px];
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -238,8 +238,8 @@ route.query.title = route.query.title || ''
|
||||
route.query.back = route.query.back || '/site/diy/list'
|
||||
|
||||
const backPath = route.query.back
|
||||
const template = ref('');
|
||||
const oldTemplate = ref('');
|
||||
const template = ref('')
|
||||
const oldTemplate = ref('')
|
||||
const wapUrl = ref('')
|
||||
const wapDomain = ref('')
|
||||
const wapPreview = ref('')
|
||||
@ -273,7 +273,7 @@ const originData = reactive({
|
||||
const isChange = ref(true) // 数据是否发生变化,true:没变化,false:变化了
|
||||
const goBack = () => {
|
||||
if (isChange.value) {
|
||||
location.href = `${location.origin}${backPath}`;
|
||||
location.href = `${location.origin}${backPath}`
|
||||
router.push(backPath)
|
||||
} else {
|
||||
// 数据发生变化,弹框提示:确定离开此页面
|
||||
@ -287,7 +287,7 @@ const goBack = () => {
|
||||
autofocus: false
|
||||
}
|
||||
).then(() => {
|
||||
location.href = `${location.origin}${backPath}`;
|
||||
location.href = `${location.origin}${backPath}`
|
||||
}).catch(() => {
|
||||
})
|
||||
}
|
||||
@ -328,7 +328,7 @@ watch(
|
||||
)
|
||||
|
||||
// 切换模板页面
|
||||
const changeTemplatePage = (value:any)=> {
|
||||
const changeTemplatePage = (value: any) => {
|
||||
// 存在数据则弹框提示确认
|
||||
if (diyStore.value.length) {
|
||||
ElMessageBox.confirm(t('changeTemplatePageTips'), t('warning'), {
|
||||
@ -337,7 +337,7 @@ const changeTemplatePage = (value:any)=> {
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
diyStore.changeCurrentIndex(-99)
|
||||
diyStore.init(); // 清空
|
||||
diyStore.init() // 清空
|
||||
if (value) {
|
||||
let data = cloneDeep(templatePages[value].data);
|
||||
diyStore.global = data.global;
|
||||
@ -349,13 +349,13 @@ const changeTemplatePage = (value:any)=> {
|
||||
}
|
||||
}).catch(() => {
|
||||
// 还原
|
||||
template.value = oldTemplate.value;
|
||||
template.value = oldTemplate.value
|
||||
});
|
||||
} else {
|
||||
diyStore.init(); // 清空
|
||||
diyStore.init() // 清空
|
||||
if (value) {
|
||||
let data = cloneDeep(templatePages[value].data);
|
||||
diyStore.global = data.global;
|
||||
let data = cloneDeep(templatePages[value].data)
|
||||
diyStore.global = data.global
|
||||
if (data.value.length) {
|
||||
diyStore.value = data.value
|
||||
}
|
||||
@ -444,7 +444,7 @@ initPage({
|
||||
}
|
||||
}
|
||||
|
||||
loadDiyTemplatePages(data.type);
|
||||
loadDiyTemplatePages(data.type)
|
||||
|
||||
// 加载预览
|
||||
wapDomain.value = data.domain_url.wap_domain
|
||||
|
||||
@ -57,14 +57,10 @@
|
||||
import { reactive, ref, watch, computed } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { img } from '@/utils/common'
|
||||
import { setDiyTheme, getDiyTheme, getDefaultTheme } from '@/app/api/diy'
|
||||
import { useClipboard } from '@vueuse/core'
|
||||
import { ElMessage, FormInstance } from 'element-plus'
|
||||
import { ArrowLeft } from '@element-plus/icons-vue'
|
||||
import { getDiyTheme } from '@/app/api/diy'
|
||||
import { useRoute } from 'vue-router'
|
||||
import themeList from './components/theme-list.vue'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import { tr } from 'element-plus/es/locale'
|
||||
|
||||
const route = useRoute()
|
||||
const pageName = route.meta.title
|
||||
@ -74,7 +70,7 @@ const data = ref([])
|
||||
|
||||
const initData = () => {
|
||||
loading.value = true;
|
||||
getDiyTheme().then((res) => {
|
||||
getDiyTheme({}).then((res) => {
|
||||
let obj = cloneDeep(res.data);
|
||||
for(let key in obj){
|
||||
obj[key].key = key;
|
||||
|
||||
@ -1,61 +1,61 @@
|
||||
<template>
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
|
||||
<!-- 表单组件 字段内容设置 -->
|
||||
<slot name="field"></slot>
|
||||
<el-form label-width="100px" class="px-[10px]">
|
||||
<el-form-item :label="t('地址格式')">
|
||||
<el-radio-group v-model="diyStore.editComponent.addressFormat" class="!block">
|
||||
<el-radio class="!block" label="province/city/district/address">{{ t('省/市/区/街道/详细地址') }}</el-radio>
|
||||
<el-radio class="!block" label="province/city/district/street">{{ t('省/市/区/街道(镇)') }}</el-radio>
|
||||
<el-radio class="!block" label="province/city/district">{{ t('省/市/区(县)') }}</el-radio>
|
||||
<el-radio class="!block" label="province/city">{{ t('省/市') }}</el-radio>
|
||||
<el-radio class="!block" label="province">{{ t('省') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<!-- 表单组件 字段内容设置 -->
|
||||
<slot name="field"></slot>
|
||||
<el-form label-width="100px" class="px-[10px]">
|
||||
<el-form-item :label="t('地址格式')">
|
||||
<el-radio-group v-model="diyStore.editComponent.addressFormat" class="!block">
|
||||
<el-radio class="!block" label="province/city/district/address">{{ t('省/市/区/街道/详细地址') }}</el-radio>
|
||||
<el-radio class="!block" label="province/city/district/street">{{ t('省/市/区/街道(镇)') }}</el-radio>
|
||||
<el-radio class="!block" label="province/city/district">{{ t('省/市/区(县)') }}</el-radio>
|
||||
<el-radio class="!block" label="province/city">{{ t('省/市') }}</el-radio>
|
||||
<el-radio class="!block" label="province">{{ t('省') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 表单组件 其他设置 -->
|
||||
<slot name="other"></slot>
|
||||
<el-form label-width="100px" class="px-[10px]">
|
||||
<el-form-item class="display-block">
|
||||
<template #label>
|
||||
<div class="flex items-center">
|
||||
<span class="mr-[3px]">{{ t('隐私保护') }}</span>
|
||||
<el-tooltip effect="light" placement="top">
|
||||
<template #content>
|
||||
<p>会自动将提交的个人信息做加密展示。</p>
|
||||
<p>适用于公开展示收集的数据且不暴露用户隐私。</p>
|
||||
</template>
|
||||
<el-icon>
|
||||
<QuestionFilled color="#999999" />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<el-switch v-model="diyStore.editComponent.field.privacyProtection" />
|
||||
<div class="text-sm text-gray-400">{{ t('提交后自动隐藏地址,仅管理员可查看') }}</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<!-- 表单组件 其他设置 -->
|
||||
<slot name="other"></slot>
|
||||
<el-form label-width="100px" class="px-[10px]">
|
||||
<el-form-item class="display-block">
|
||||
<template #label>
|
||||
<div class="flex items-center">
|
||||
<span class="mr-[3px]">{{ t('隐私保护') }}</span>
|
||||
<el-tooltip effect="light" placement="top">
|
||||
<template #content>
|
||||
<p>会自动将提交的个人信息做加密展示。</p>
|
||||
<p>适用于公开展示收集的数据且不暴露用户隐私。</p>
|
||||
</template>
|
||||
<el-icon>
|
||||
<QuestionFilled color="#999999" />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<el-switch v-model="diyStore.editComponent.field.privacyProtection" :disabled ="diyStore.editComponent.addressFormat != 'province/city/district/address'" />
|
||||
<div class="text-sm text-gray-400">{{ t('提交后自动隐藏地址,仅管理员可查看') }}</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
|
||||
<!-- 表单组件 字段样式 -->
|
||||
<slot name="style-field"></slot>
|
||||
<!-- 表单组件 字段样式 -->
|
||||
<slot name="style-field"></slot>
|
||||
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { t } from '@/lang'
|
||||
import { ref } from 'vue'
|
||||
import { ref,watch } from 'vue'
|
||||
import useDiyStore from '@/stores/modules/diy'
|
||||
|
||||
const diyStore = useDiyStore()
|
||||
@ -63,9 +63,18 @@ diyStore.editComponent.ignore = ['componentBgUrl'] // 忽略公共属性
|
||||
|
||||
// 组件验证
|
||||
diyStore.editComponent.verify = (index: number) => {
|
||||
const res = { code: true, message: '' }
|
||||
return res
|
||||
const res = { code: true, message: '' }
|
||||
return res
|
||||
}
|
||||
watch(
|
||||
() => diyStore.editComponent.addressFormat,
|
||||
(newVal) => {
|
||||
if (newVal !== 'province/city/district/address') {
|
||||
diyStore.editComponent.field.privacyProtection = false
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
defineExpose({})
|
||||
|
||||
|
||||
@ -1,81 +1,81 @@
|
||||
<template>
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
|
||||
<!-- 表单组件 字段内容设置 -->
|
||||
<slot name="field"></slot>
|
||||
<el-form label-width="100px" class="px-[10px]">
|
||||
<el-form-item :label="t('style')">
|
||||
<el-radio-group v-model="diyStore.editComponent.style">
|
||||
<el-radio label="style-1">{{ t('defaultSources') }}</el-radio>
|
||||
<el-radio label="style-2">{{ t('listStyle') }}</el-radio>
|
||||
<el-radio label="style-3">{{ t('dropDownStyle') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('option')">
|
||||
<!-- 表单组件 字段内容设置 -->
|
||||
<slot name="field"></slot>
|
||||
<el-form label-width="100px" class="px-[10px]">
|
||||
<el-form-item :label="t('style')">
|
||||
<el-radio-group v-model="diyStore.editComponent.style">
|
||||
<el-radio label="style-1">{{ t('defaultSources') }}</el-radio>
|
||||
<el-radio label="style-2">{{ t('listStyle') }}</el-radio>
|
||||
<el-radio label="style-3">{{ t('dropDownStyle') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('option')">
|
||||
<div ref="formCheckboxRef">
|
||||
<div v-for="(option, index) in diyStore.editComponent.options" :key="option.id" class="option-item flex items-center mb-[15px]">
|
||||
<el-input v-model="diyStore.editComponent.options[index].text" class="!w-[215px]" :placeholder="t('optionPlaceholder')" maxlength="30" clearable />
|
||||
<span v-if="diyStore.editComponent.options.length > 1" @click="removeOption(index)" class="cursor-pointer ml-[5px] nc-iconfont nc-icon-shanchu-yuangaizhiV6xx"></span>
|
||||
</div>
|
||||
</div>
|
||||
<span class="text-primary cursor-pointer mr-[10px]" @click="addOption">{{ t('addSingleOption') }}</span>
|
||||
<el-popover :visible="visible" placement="bottom" :width="300">
|
||||
<p class="mb-[5px]">{{ t('addMultipleOption') }}</p>
|
||||
<p class="text-[#888] text-[12px] mb-[5px]">{{ t('addOptionTips') }}</p>
|
||||
<el-input v-model.trim="optionsValue" type="textarea" clearable maxlength="200" show-word-limit />
|
||||
<div class="mt-[10px] text-right">
|
||||
<el-button size="small" text @click="visible = false">{{ t('cancel') }}</el-button>
|
||||
<el-button size="small" type="primary" @click="batchAddOptions">{{ t('confirm') }}</el-button>
|
||||
</div>
|
||||
<template #reference>
|
||||
<span class="text-primary cursor-pointer" @click="visible = true">{{ t('addMultipleOption') }}</span>
|
||||
</template>
|
||||
</el-popover>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<span class="text-primary cursor-pointer mr-[10px]" @click="addOption">{{ t('addSingleOption') }}</span>
|
||||
<el-popover :visible="visible" placement="bottom" :width="300">
|
||||
<p class="mb-[5px]">{{ t('addMultipleOption') }}</p>
|
||||
<p class="text-[#888] text-[12px] mb-[5px]">{{ t('addOptionTips') }}</p>
|
||||
<el-input v-model.trim="optionsValue" type="textarea" clearable maxlength="200" show-word-limit />
|
||||
<div class="mt-[10px] text-right">
|
||||
<el-button size="small" text @click="visible = false">{{ t('cancel') }}</el-button>
|
||||
<el-button size="small" type="primary" @click="batchAddOptions">{{ t('confirm') }}</el-button>
|
||||
</div>
|
||||
<template #reference>
|
||||
<span class="text-primary cursor-pointer" @click="visible = true">{{ t('addMultipleOption') }}</span>
|
||||
</template>
|
||||
</el-popover>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 表单组件 其他设置 -->
|
||||
<slot name="other"></slot>
|
||||
<!-- <el-form label-width="100px" class="px-[10px]">-->
|
||||
<!-- <el-form-item class="display-block">-->
|
||||
<!-- <template #label>-->
|
||||
<!-- <div class="flex items-center">-->
|
||||
<!-- <span class="mr-[3px]">{{ t('隐私保护') }}</span>-->
|
||||
<!-- <el-tooltip effect="light" placement="top">-->
|
||||
<!-- <template #content>-->
|
||||
<!-- <p>会自动将提交的个人信息做加密展示。</p>-->
|
||||
<!-- <p>适用于公开展示收集的数据且不暴露用户隐私。</p>-->
|
||||
<!-- </template>-->
|
||||
<!-- <el-icon>-->
|
||||
<!-- <QuestionFilled color="#999999" />-->
|
||||
<!-- </el-icon>-->
|
||||
<!-- </el-tooltip>-->
|
||||
<!-- </div>-->
|
||||
<!-- </template>-->
|
||||
<!-- <el-switch v-model="diyStore.editComponent.field.privacyProtection" />-->
|
||||
<!-- <div class="text-sm text-gray-400">{{ t('提交后自动隐藏内容,仅管理员可查看') }}</div>-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- 表单组件 其他设置 -->
|
||||
<slot name="other"></slot>
|
||||
<!-- <el-form label-width="100px" class="px-[10px]">-->
|
||||
<!-- <el-form-item class="display-block">-->
|
||||
<!-- <template #label>-->
|
||||
<!-- <div class="flex items-center">-->
|
||||
<!-- <span class="mr-[3px]">{{ t('隐私保护') }}</span>-->
|
||||
<!-- <el-tooltip effect="light" placement="top">-->
|
||||
<!-- <template #content>-->
|
||||
<!-- <p>会自动将提交的个人信息做加密展示。</p>-->
|
||||
<!-- <p>适用于公开展示收集的数据且不暴露用户隐私。</p>-->
|
||||
<!-- </template>-->
|
||||
<!-- <el-icon>-->
|
||||
<!-- <QuestionFilled color="#999999" />-->
|
||||
<!-- </el-icon>-->
|
||||
<!-- </el-tooltip>-->
|
||||
<!-- </div>-->
|
||||
<!-- </template>-->
|
||||
<!-- <el-switch v-model="diyStore.editComponent.field.privacyProtection" />-->
|
||||
<!-- <div class="text-sm text-gray-400">{{ t('提交后自动隐藏内容,仅管理员可查看') }}</div>-->
|
||||
<!-- </el-form-item>-->
|
||||
|
||||
<!-- </el-form>-->
|
||||
<!-- </el-form>-->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
|
||||
<!-- 表单组件 字段样式 -->
|
||||
<slot name="style-field"></slot>
|
||||
<!-- 表单组件 字段样式 -->
|
||||
<slot name="style-field"></slot>
|
||||
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { t } from '@/lang'
|
||||
import { ref, onMounted, nextTick} from 'vue'
|
||||
import { ref, onMounted, nextTick } from 'vue'
|
||||
import useDiyStore from '@/stores/modules/diy'
|
||||
import Sortable from 'sortablejs'
|
||||
import { range } from 'lodash-es'
|
||||
@ -86,84 +86,84 @@ diyStore.editComponent.ignore = ['componentBgUrl'] // 忽略公共属性
|
||||
|
||||
// 组件验证
|
||||
diyStore.editComponent.verify = (index: number) => {
|
||||
const res = { code: true, message: '' }
|
||||
let pass = true;
|
||||
for (let i = 0; i < diyStore.value[index].options.length; i++) {
|
||||
if (!diyStore.value[index].options[i].text) {
|
||||
res.code = false;
|
||||
res.message = t('optionPlaceholder');
|
||||
pass = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
const res = { code: true, message: '' }
|
||||
let pass = true;
|
||||
for (let i = 0; i < diyStore.value[index].options.length; i++) {
|
||||
if (!diyStore.value[index].options[i].text) {
|
||||
res.code = false;
|
||||
res.message = t('optionPlaceholder');
|
||||
pass = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!pass) return res;
|
||||
if (!pass) return res;
|
||||
|
||||
let uniqueOptions = uniqueByKey(diyStore.value[index].options, 'text')
|
||||
if (uniqueOptions.length != diyStore.value[index].options.length) {
|
||||
res.code = false;
|
||||
res.message = t('errorTipsOne')
|
||||
}
|
||||
return res
|
||||
let uniqueOptions = uniqueByKey(diyStore.value[index].options, 'text')
|
||||
if (uniqueOptions.length != diyStore.value[index].options.length) {
|
||||
res.code = false;
|
||||
res.message = t('errorTipsOne')
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
diyStore.editComponent.options.forEach((item: any) => {
|
||||
if (!item.id) item.id = diyStore.generateRandom()
|
||||
if (!item.id) item.id = diyStore.generateRandom()
|
||||
})
|
||||
|
||||
const visible = ref(false)
|
||||
const optionsValue = ref()
|
||||
const addOption = () => {
|
||||
diyStore.editComponent.options.push({
|
||||
id: diyStore.generateRandom(),
|
||||
text: '选项' + (diyStore.editComponent.options.length + 1)
|
||||
});
|
||||
diyStore.editComponent.options.push({
|
||||
id: diyStore.generateRandom(),
|
||||
text: '选项' + (diyStore.editComponent.options.length + 1)
|
||||
});
|
||||
};
|
||||
|
||||
const removeOption = (index:any) => {
|
||||
const removeOption = (index: any) => {
|
||||
diyStore.editComponent.options.splice(index, 1);
|
||||
}
|
||||
|
||||
// 批量添加选项
|
||||
const batchAddOptions = () => {
|
||||
if (optionsValue.value.trim()) {
|
||||
const newOptions = optionsValue.value.split(',').map((option: any) => {
|
||||
return {
|
||||
id: diyStore.generateRandom(),
|
||||
text: option.trim()
|
||||
};
|
||||
}).filter((option: any) => option.text !== '');
|
||||
if (optionsValue.value.trim()) {
|
||||
const newOptions = optionsValue.value.split(',').map((option: any) => {
|
||||
return {
|
||||
id: diyStore.generateRandom(),
|
||||
text: option.trim()
|
||||
};
|
||||
}).filter((option: any) => option.text !== '');
|
||||
|
||||
// 去除重复的选项
|
||||
const uniqueNewOptions = uniqueByKey(newOptions, 'text');
|
||||
// 去除重复的选项
|
||||
const uniqueNewOptions = uniqueByKey(newOptions, 'text');
|
||||
|
||||
// 过滤掉已存在的选项
|
||||
const filteredNewOptions = uniqueNewOptions.filter((newOption: any) =>
|
||||
!diyStore.editComponent.options.some((existingOption: any) => existingOption.text === newOption.text)
|
||||
);
|
||||
// 过滤掉已存在的选项
|
||||
const filteredNewOptions = uniqueNewOptions.filter((newOption: any) =>
|
||||
!diyStore.editComponent.options.some((existingOption: any) => existingOption.text === newOption.text)
|
||||
);
|
||||
|
||||
// 如果有新的选项,添加到选项列表中
|
||||
if (filteredNewOptions.length > 0) {
|
||||
diyStore.editComponent.options.push(...filteredNewOptions);
|
||||
} else {
|
||||
ElMessage({
|
||||
message: t('errorTipsTwo'),
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
// 如果有新的选项,添加到选项列表中
|
||||
if (filteredNewOptions.length > 0) {
|
||||
diyStore.editComponent.options.push(...filteredNewOptions);
|
||||
} else {
|
||||
ElMessage({
|
||||
message: t('errorTipsTwo'),
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
|
||||
optionsValue.value = '';
|
||||
visible.value = false;
|
||||
}
|
||||
optionsValue.value = '';
|
||||
visible.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 数组去重
|
||||
const uniqueByKey = (arr: any, key: any) => {
|
||||
const seen = new Set();
|
||||
return arr.filter((item: any) => {
|
||||
const serializedKey = JSON.stringify(item[key]);
|
||||
return seen.has(serializedKey) ? false : seen.add(serializedKey);
|
||||
});
|
||||
const seen = new Set();
|
||||
return arr.filter((item: any) => {
|
||||
const serializedKey = JSON.stringify(item[key]);
|
||||
return seen.has(serializedKey) ? false : seen.add(serializedKey);
|
||||
});
|
||||
}
|
||||
|
||||
const formCheckboxRef = ref()
|
||||
|
||||
@ -1,93 +1,98 @@
|
||||
<template>
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
|
||||
<!-- 表单组件 字段内容设置 -->
|
||||
<slot name="field"></slot>
|
||||
<el-form label-width="100px" class="px-[10px]">
|
||||
<el-form-item :label="t('dataFormat')">
|
||||
<el-radio-group v-model="diyStore.editComponent.dateFormat">
|
||||
<div class="flex flex-col">
|
||||
<!-- 表单组件 字段内容设置 -->
|
||||
<slot name="field"></slot>
|
||||
<el-form label-width="100px" class="px-[10px]">
|
||||
<el-form-item :label="t('dataFormat')">
|
||||
<el-radio-group v-model="diyStore.editComponent.dateFormat">
|
||||
<div class="flex flex-col">
|
||||
<el-radio label="YYYY年M月D日">{{ dateFormat.format1 }}</el-radio>
|
||||
<el-radio label="YYYY-MM-DD">{{ dateFormat.format2 }}</el-radio>
|
||||
<el-radio label="YYYY/MM/DD">{{ dateFormat.format3 }}</el-radio>
|
||||
</div>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('startDate') }}</h3>
|
||||
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
|
||||
<el-form-item :label="t('formPlaceholder')">
|
||||
<el-input v-model.trim="diyStore.editComponent.start.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('defaultValue')">
|
||||
<el-switch v-model="diyStore.editComponent.start.defaultControl" />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="diyStore.editComponent.start.defaultControl">
|
||||
<el-radio-group v-model="diyStore.editComponent.start.dateWay">
|
||||
<el-radio label="current">{{ t('currentDate') }}</el-radio>
|
||||
<el-radio label="diy">{{ t('diyDate') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="diyStore.editComponent.start.defaultControl && diyStore.editComponent.start.dateWay == 'diy'">
|
||||
<el-date-picker v-model="diyStore.editComponent.field.default.start.date" format="YYYY/MM/DD" value-format="YYYY-MM-DD" type="date" :placeholder="t('startDataPlaceholder')" @change="startDateChange" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('startDate') }}</h3>
|
||||
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
|
||||
<el-form-item :label="t('formPlaceholder')">
|
||||
<el-input v-model.trim="diyStore.editComponent.start.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('defaultValue')">
|
||||
<el-switch v-model="diyStore.editComponent.start.defaultControl" />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="diyStore.editComponent.start.defaultControl">
|
||||
<el-radio-group v-model="diyStore.editComponent.start.dateWay">
|
||||
<el-radio label="current">{{ t('currentDate') }}</el-radio>
|
||||
<el-radio label="diy">{{ t('diyDate') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="diyStore.editComponent.start.defaultControl && diyStore.editComponent.start.dateWay == 'diy'">
|
||||
<el-date-picker v-model="diyStore.editComponent.field.default.start.date" format="YYYY/MM/DD" value-format="YYYY-MM-DD" type="date" :placeholder="t('startDataPlaceholder')" @change="startDateChange" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('endDate') }}</h3>
|
||||
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
|
||||
<el-form-item :label="t('formPlaceholder')">
|
||||
<el-input v-model.trim="diyStore.editComponent.end.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('defaultValue')">
|
||||
<el-switch v-model="diyStore.editComponent.end.defaultControl" />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="diyStore.editComponent.end.defaultControl">
|
||||
<el-radio-group v-model="diyStore.editComponent.end.dateWay">
|
||||
<el-radio label="current">{{ t('currentDate') }}</el-radio>
|
||||
<el-radio label="diy">{{ t('diyDate') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="diyStore.editComponent.end.defaultControl && diyStore.editComponent.end.dateWay == 'diy'">
|
||||
<el-date-picker :disabled-date="disabledEndDate" v-model="diyStore.editComponent.field.default.end.date" format="YYYY/MM/DD" value-format="YYYY-MM-DD" type="date" :placeholder="t('endDataPlaceholder')" @change="endDateChange" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('endDate') }}</h3>
|
||||
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
|
||||
<el-form-item :label="t('formPlaceholder')">
|
||||
<el-input v-model.trim="diyStore.editComponent.end.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('defaultValue')">
|
||||
<el-switch v-model="diyStore.editComponent.end.defaultControl" />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="diyStore.editComponent.end.defaultControl">
|
||||
<el-radio-group v-model="diyStore.editComponent.end.dateWay">
|
||||
<el-radio label="current">{{ t('currentDate') }}</el-radio>
|
||||
<el-radio label="diy">{{ t('diyDate') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="diyStore.editComponent.end.defaultControl && diyStore.editComponent.end.dateWay == 'diy'">
|
||||
<el-date-picker :disabled-date="disabledEndDate"
|
||||
v-model="diyStore.editComponent.field.default.end.date" format="YYYY/MM/DD"
|
||||
value-format="YYYY-MM-DD" type="date" :placeholder="t('endDataPlaceholder')"
|
||||
@change="endDateChange" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<!-- 表单组件 其他设置 -->
|
||||
<slot name="other"></slot>
|
||||
<!-- 表单组件 其他设置 -->
|
||||
<slot name="other"></slot>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('textStyle') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('textFontSize')">
|
||||
<el-slider v-model="diyStore.editComponent.fontSize" show-input size="small" class="ml-[10px] diy-nav-slider" :min="12" :max="18" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('textFontWeight')">
|
||||
<el-radio-group v-model="diyStore.editComponent.fontWeight">
|
||||
<el-radio :label="'normal'">{{ t('fontWeightNormal') }}</el-radio>
|
||||
<el-radio :label="'bold'">{{ t('fontWeightBold') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('textColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.textColor" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('textStyle') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('textFontSize')">
|
||||
<el-slider v-model="diyStore.editComponent.fontSize" show-input size="small" class="ml-[10px] diy-nav-slider" :min="12" :max="18" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('textFontWeight')">
|
||||
<el-radio-group v-model="diyStore.editComponent.fontWeight">
|
||||
<el-radio :label="'normal'">{{ t('fontWeightNormal') }}</el-radio>
|
||||
<el-radio :label="'bold'">{{ t('fontWeightBold') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('textColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.textColor" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
@ -142,7 +147,7 @@ const dateFormat: any = reactive({
|
||||
})
|
||||
|
||||
// 结束日期-禁止的日期
|
||||
const disabledEndDate = (time:Date)=>{
|
||||
const disabledEndDate = (time: Date) => {
|
||||
let cutoffDate = null
|
||||
let bool = false
|
||||
if (diyStore.editComponent.start && diyStore.editComponent.start.defaultControl) {
|
||||
@ -177,10 +182,10 @@ onMounted(() => {
|
||||
|
||||
const hours = String(today.getHours()).padStart(2, '0')
|
||||
const minutes = String(today.getMinutes()).padStart(2, '0')
|
||||
dateFormat.format1 = `${year}年${month}月${day}日`
|
||||
dateFormat.format2 = `${year}-${month}-${day}`
|
||||
dateFormat.format3 = `${year}/${month}/${day}`
|
||||
dateFormat.format4 = `${year}-${month}-${day} ${hours}:${minutes}`
|
||||
dateFormat.format1 = `${ year }年${ month }月${ day }日`
|
||||
dateFormat.format2 = `${ year }-${ month }-${ day }`
|
||||
dateFormat.format3 = `${ year }/${ month }/${ day }`
|
||||
dateFormat.format4 = `${ year }-${ month }-${ day } ${ hours }:${ minutes }`
|
||||
})
|
||||
|
||||
// 开始日期选择器
|
||||
|
||||
@ -1,56 +1,56 @@
|
||||
<template>
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
|
||||
<!-- 表单组件 字段内容设置 -->
|
||||
<slot name="field"></slot>
|
||||
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
|
||||
<el-form-item :label="t('dataFormat')">
|
||||
<el-radio-group v-model="diyStore.editComponent.dateFormat" class="!block">
|
||||
<el-radio class="!block" label="YYYY年M月D日">{{ dateFormat.format1 }}</el-radio>
|
||||
<el-radio class="!block" label="YYYY-MM-DD">{{ dateFormat.format2 }}</el-radio>
|
||||
<el-radio class="!block" label="YYYY/MM/DD">{{ dateFormat.format3 }}</el-radio>
|
||||
<el-radio class="!block" label="YYYY-MM-DD HH:mm">{{ dateFormat.format4 }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('formPlaceholder')">
|
||||
<el-input v-model.trim="diyStore.editComponent.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('defaultValue')">
|
||||
<el-switch v-model="diyStore.editComponent.defaultControl"/>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="diyStore.editComponent.defaultControl">
|
||||
<el-radio-group v-model="diyStore.editComponent.dateWay">
|
||||
<el-radio label="current">{{ t('currentDate') }}</el-radio>
|
||||
<el-radio label="diy">{{ t('diyDate') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="diyStore.editComponent.defaultControl && diyStore.editComponent.dateWay == 'diy'">
|
||||
<el-date-picker v-if="diyStore.editComponent.dateFormat != 'YYYY-MM-DD HH:mm'" v-model="diyStore.editComponent.field.default.date" format="YYYY/MM/DD" value-format="YYYY-MM-DD" type="date" :placeholder="t('dataPlaceholder')" @change="dateChange"/>
|
||||
<el-date-picker v-else v-model="diyStore.editComponent.field.default.date" format="YYYY/MM/DD HH:mm" value-format="YYYY-MM-DD HH:mm" type="datetime" :placeholder="t('dataPlaceholder')" @change="dateChange"/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<!-- 表单组件 字段内容设置 -->
|
||||
<slot name="field"></slot>
|
||||
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
|
||||
<el-form-item :label="t('dataFormat')">
|
||||
<el-radio-group v-model="diyStore.editComponent.dateFormat" class="!block">
|
||||
<el-radio class="!block" label="YYYY年M月D日">{{ dateFormat.format1 }}</el-radio>
|
||||
<el-radio class="!block" label="YYYY-MM-DD">{{ dateFormat.format2 }}</el-radio>
|
||||
<el-radio class="!block" label="YYYY/MM/DD">{{ dateFormat.format3 }}</el-radio>
|
||||
<el-radio class="!block" label="YYYY-MM-DD HH:mm">{{ dateFormat.format4 }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('formPlaceholder')">
|
||||
<el-input v-model.trim="diyStore.editComponent.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('defaultValue')">
|
||||
<el-switch v-model="diyStore.editComponent.defaultControl" />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="diyStore.editComponent.defaultControl">
|
||||
<el-radio-group v-model="diyStore.editComponent.dateWay">
|
||||
<el-radio label="current">{{ t('currentDate') }}</el-radio>
|
||||
<el-radio label="diy">{{ t('diyDate') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="diyStore.editComponent.defaultControl && diyStore.editComponent.dateWay == 'diy'">
|
||||
<el-date-picker v-if="diyStore.editComponent.dateFormat != 'YYYY-MM-DD HH:mm'" v-model="diyStore.editComponent.field.default.date" format="YYYY/MM/DD" value-format="YYYY-MM-DD" type="date" :placeholder="t('dataPlaceholder')" @change="dateChange" />
|
||||
<el-date-picker v-else v-model="diyStore.editComponent.field.default.date" format="YYYY/MM/DD HH:mm" value-format="YYYY-MM-DD HH:mm" type="datetime" :placeholder="t('dataPlaceholder')" @change="dateChange" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 表单组件 其他设置 -->
|
||||
<slot name="other"></slot>
|
||||
<!-- 表单组件 其他设置 -->
|
||||
<slot name="other"></slot>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
|
||||
<!-- 表单组件 字段样式 -->
|
||||
<slot name="style-field"></slot>
|
||||
<!-- 表单组件 字段样式 -->
|
||||
<slot name="style-field"></slot>
|
||||
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { t } from '@/lang'
|
||||
import { ref,reactive,watch,onMounted } from 'vue'
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import { timeTurnTimeStamp } from '@/utils/common'
|
||||
import useDiyStore from '@/stores/modules/diy'
|
||||
|
||||
@ -64,16 +64,16 @@ diyStore.editComponent.verify = (index: number) => {
|
||||
}
|
||||
|
||||
const dateFormat: any = reactive({
|
||||
format1: '',
|
||||
format2: '',
|
||||
format3: '',
|
||||
format4: ''
|
||||
format1: '',
|
||||
format2: '',
|
||||
format3: '',
|
||||
format4: ''
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
// 初始赋值当天日期
|
||||
const today = new Date();
|
||||
if (!diyStore.editComponent.field.default.date) {
|
||||
if (!diyStore.editComponent.field.default.date) {
|
||||
diyStore.editComponent.field.default.date = today.toISOString().split('T')[0];
|
||||
diyStore.editComponent.field.default.timestamp = today.getTime() / 1000;
|
||||
}
|
||||
@ -83,13 +83,13 @@ onMounted(() => {
|
||||
|
||||
const hours = String(today.getHours()).padStart(2, '0');
|
||||
const minutes = String(today.getMinutes()).padStart(2, '0');
|
||||
dateFormat.format1 = `${year}年${month}月${day}日`;
|
||||
dateFormat.format2 = `${year}-${month}-${day}`;
|
||||
dateFormat.format3 = `${year}/${month}/${day}`;
|
||||
dateFormat.format4 = `${year}-${month}-${day} ${hours}:${minutes}`;
|
||||
dateFormat.format1 = `${ year }年${ month }月${ day }日`;
|
||||
dateFormat.format2 = `${ year }-${ month }-${ day }`;
|
||||
dateFormat.format3 = `${ year }/${ month }/${ day }`;
|
||||
dateFormat.format4 = `${ year }-${ month }-${ day } ${ hours }:${ minutes }`;
|
||||
});
|
||||
|
||||
const dateChange = (date: any)=>{
|
||||
const dateChange = (date: any) => {
|
||||
diyStore.editComponent.field.default.date = date;
|
||||
diyStore.editComponent.field.default.timestamp = timeTurnTimeStamp(date);
|
||||
}
|
||||
|
||||
@ -1,30 +1,30 @@
|
||||
<template>
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
|
||||
<!-- 表单组件 字段内容设置 -->
|
||||
<slot name="field"></slot>
|
||||
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
|
||||
<el-form-item :label="t('formPlaceholder')">
|
||||
<el-input v-model.trim="diyStore.editComponent.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<!-- 表单组件 字段内容设置 -->
|
||||
<slot name="field"></slot>
|
||||
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
|
||||
<el-form-item :label="t('formPlaceholder')">
|
||||
<el-input v-model.trim="diyStore.editComponent.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 表单组件 其他设置 -->
|
||||
<slot name="other"></slot>
|
||||
<!-- 表单组件 其他设置 -->
|
||||
<slot name="other"></slot>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
|
||||
<!-- 表单组件 字段样式 -->
|
||||
<slot name="style-field"></slot>
|
||||
<!-- 表单组件 字段样式 -->
|
||||
<slot name="style-field"></slot>
|
||||
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
@ -38,7 +38,7 @@ diyStore.editComponent.ignore = ['componentBgUrl'] // 忽略公共属性
|
||||
// 组件验证
|
||||
diyStore.editComponent.verify = (index: number) => {
|
||||
const res = { code: true, message: '' }
|
||||
// todo 只需要考虑该组件自身的验证
|
||||
// todo 只需要考虑该组件自身的验证
|
||||
return res
|
||||
}
|
||||
defineExpose({})
|
||||
|
||||
@ -1,31 +1,31 @@
|
||||
<template>
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
|
||||
<!-- 表单组件 字段内容设置 -->
|
||||
<slot name="field"></slot>
|
||||
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
|
||||
<el-form-item :label="t('限制上传大小')">
|
||||
<el-input v-model.trim="diyStore.editComponent.limitUploadSize" clearable maxlength="15" />
|
||||
/单位MB,目前是Bit,要转换,*1024
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<!-- 表单组件 字段内容设置 -->
|
||||
<slot name="field"></slot>
|
||||
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
|
||||
<el-form-item :label="t('限制上传大小')">
|
||||
<el-input v-model.trim="diyStore.editComponent.limitUploadSize" clearable maxlength="15" />
|
||||
/单位MB,目前是Bit,要转换,*1024
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 表单组件 其他设置 -->
|
||||
<slot name="other"></slot>
|
||||
<!-- 表单组件 其他设置 -->
|
||||
<slot name="other"></slot>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
|
||||
<!-- 表单组件 字段样式 -->
|
||||
<slot name="style-field"></slot>
|
||||
<!-- 表单组件 字段样式 -->
|
||||
<slot name="style-field"></slot>
|
||||
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
||||
@ -1,67 +1,67 @@
|
||||
<template>
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
|
||||
<!-- 表单组件 字段内容设置 -->
|
||||
<slot name="field"></slot>
|
||||
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
|
||||
<el-form-item :label="t('formPlaceholder')">
|
||||
<el-input v-model.trim="diyStore.editComponent.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<!-- 表单组件 字段内容设置 -->
|
||||
<slot name="field"></slot>
|
||||
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
|
||||
<el-form-item :label="t('formPlaceholder')">
|
||||
<el-input v-model.trim="diyStore.editComponent.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 表单组件 其他设置 -->
|
||||
<slot name="other"></slot>
|
||||
<el-form label-width="100px" class="px-[10px]">
|
||||
<el-form-item>
|
||||
<template #label>
|
||||
<div class="flex items-center">
|
||||
<span class="mr-[3px]">{{ t('preventDuplication') }}</span>
|
||||
<el-tooltip effect="light" placement="top">
|
||||
<template #content>
|
||||
<p>{{ t('preventDuplicationTipsOne') }}</p>
|
||||
<p>{{ t('preventDuplicationTipsTwo') }}</p>
|
||||
</template>
|
||||
<el-icon>
|
||||
<QuestionFilled color="#999999" />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<el-switch v-model="diyStore.editComponent.field.unique" />
|
||||
</el-form-item>
|
||||
<el-form-item class="display-block">
|
||||
<template #label>
|
||||
<div class="flex items-center">
|
||||
<span class="mr-[3px]">{{ t('privacyProtection') }}</span>
|
||||
<el-tooltip effect="light" placement="top">
|
||||
<template #content>
|
||||
<p>{{ t('privacyProtectionTipsOne') }}</p>
|
||||
<p>{{ t('privacyProtectionTipsTwo') }}</p>
|
||||
</template>
|
||||
<el-icon>
|
||||
<QuestionFilled color="#999999" />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<el-switch v-model="diyStore.editComponent.field.privacyProtection" />
|
||||
<div class="text-sm text-gray-400">{{ t('privacyProtectionTipsThree') }}</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<!-- 表单组件 其他设置 -->
|
||||
<slot name="other"></slot>
|
||||
<el-form label-width="100px" class="px-[10px]">
|
||||
<el-form-item>
|
||||
<template #label>
|
||||
<div class="flex items-center">
|
||||
<span class="mr-[3px]">{{ t('preventDuplication') }}</span>
|
||||
<el-tooltip effect="light" placement="top">
|
||||
<template #content>
|
||||
<p>{{ t('preventDuplicationTipsOne') }}</p>
|
||||
<p>{{ t('preventDuplicationTipsTwo') }}</p>
|
||||
</template>
|
||||
<el-icon>
|
||||
<QuestionFilled color="#999999" />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<el-switch v-model="diyStore.editComponent.field.unique" />
|
||||
</el-form-item>
|
||||
<el-form-item class="display-block">
|
||||
<template #label>
|
||||
<div class="flex items-center">
|
||||
<span class="mr-[3px]">{{ t('privacyProtection') }}</span>
|
||||
<el-tooltip effect="light" placement="top">
|
||||
<template #content>
|
||||
<p>{{ t('privacyProtectionTipsOne') }}</p>
|
||||
<p>{{ t('privacyProtectionTipsTwo') }}</p>
|
||||
</template>
|
||||
<el-icon>
|
||||
<QuestionFilled color="#999999" />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<el-switch v-model="diyStore.editComponent.field.privacyProtection" />
|
||||
<div class="text-sm text-gray-400">{{ t('privacyProtectionTipsThree') }}</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
|
||||
<!-- 表单组件 字段样式 -->
|
||||
<slot name="style-field"></slot>
|
||||
<!-- 表单组件 字段样式 -->
|
||||
<slot name="style-field"></slot>
|
||||
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
@ -75,7 +75,7 @@ diyStore.editComponent.ignore = ['componentBgUrl'] // 忽略公共属性
|
||||
// 组件验证
|
||||
diyStore.editComponent.verify = (index: number) => {
|
||||
const res = { code: true, message: '' }
|
||||
// todo 只需要考虑该组件自身的验证
|
||||
// todo 只需要考虑该组件自身的验证
|
||||
return res
|
||||
}
|
||||
defineExpose({})
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
<template>
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
|
||||
<!-- 表单组件 字段内容设置 -->
|
||||
<slot name="field"></slot>
|
||||
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
|
||||
<el-form-item :label="t('imageLimit')">
|
||||
<el-input v-model.trim="diyStore.editComponent.limit" :placeholder="t('imageLimitPlaceholder')" clearable maxlength="2" />
|
||||
</el-form-item>
|
||||
<!-- 表单组件 字段内容设置 -->
|
||||
<slot name="field"></slot>
|
||||
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
|
||||
<el-form-item :label="t('imageLimit')">
|
||||
<el-input v-model.trim="diyStore.editComponent.limit" :placeholder="t('imageLimitPlaceholder')" clearable maxlength="2" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('上传方式')">
|
||||
<el-checkbox-group v-model="diyStore.editComponent.uploadMode" :min="1">
|
||||
@ -15,23 +15,23 @@
|
||||
<el-checkbox label="从相册选择" value="select_from_album" />
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-form>
|
||||
|
||||
<!-- 表单组件 其他设置 -->
|
||||
<slot name="other"></slot>
|
||||
<!-- 表单组件 其他设置 -->
|
||||
<slot name="other"></slot>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
|
||||
<!-- 表单组件 字段样式 -->
|
||||
<slot name="style-field"></slot>
|
||||
<!-- 表单组件 字段样式 -->
|
||||
<slot name="style-field"></slot>
|
||||
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
||||
@ -1,80 +1,80 @@
|
||||
<template>
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
|
||||
<!-- 表单组件 字段内容设置 -->
|
||||
<slot name="field"></slot>
|
||||
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
|
||||
<el-form-item :label="t('formPlaceholder')">
|
||||
<el-input v-model.trim="diyStore.editComponent.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template #label>
|
||||
<div class="flex items-center">
|
||||
<span class="mr-[3px]">{{ t('defaultValue') }}</span>
|
||||
<el-tooltip effect="light" :content="t('defaultValueTips')" placement="top">
|
||||
<el-icon>
|
||||
<QuestionFilled color="#999999" />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<el-input v-model.trim="diyStore.editComponent.field.default" :placeholder="t('defaultValuePlaceholder')" clearable maxlength="18" show-word-limit />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<!-- 表单组件 字段内容设置 -->
|
||||
<slot name="field"></slot>
|
||||
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
|
||||
<el-form-item :label="t('formPlaceholder')">
|
||||
<el-input v-model.trim="diyStore.editComponent.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template #label>
|
||||
<div class="flex items-center">
|
||||
<span class="mr-[3px]">{{ t('defaultValue') }}</span>
|
||||
<el-tooltip effect="light" :content="t('defaultValueTips')" placement="top">
|
||||
<el-icon>
|
||||
<QuestionFilled color="#999999" />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<el-input v-model.trim="diyStore.editComponent.field.default" :placeholder="t('defaultValuePlaceholder')" clearable maxlength="18" show-word-limit />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 表单组件 其他设置 -->
|
||||
<slot name="other"></slot>
|
||||
<el-form label-width="100px" class="px-[10px]">
|
||||
<el-form-item>
|
||||
<template #label>
|
||||
<div class="flex items-center">
|
||||
<span class="mr-[3px]">{{ t('preventDuplication') }}</span>
|
||||
<el-tooltip effect="light" placement="top">
|
||||
<template #content>
|
||||
<p>{{ t('preventDuplicationTipsOne') }}</p>
|
||||
<p>{{ t('preventDuplicationTipsTwo') }}</p>
|
||||
</template>
|
||||
<el-icon>
|
||||
<QuestionFilled color="#999999" />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<el-switch v-model="diyStore.editComponent.field.unique" />
|
||||
</el-form-item>
|
||||
<!-- <el-form-item class="display-block">-->
|
||||
<!-- <template #label>-->
|
||||
<!-- <div class="flex items-center">-->
|
||||
<!-- <span class="mr-[3px]">{{ t('隐私保护') }}</span>-->
|
||||
<!-- <el-tooltip effect="light" placement="top">-->
|
||||
<!-- <template #content>-->
|
||||
<!-- <p>会自动将提交的个人信息做加密展示。</p>-->
|
||||
<!-- <p>适用于公开展示收集的数据且不暴露用户隐私。</p>-->
|
||||
<!-- </template>-->
|
||||
<!-- <el-icon>-->
|
||||
<!-- <QuestionFilled color="#999999" />-->
|
||||
<!-- </el-icon>-->
|
||||
<!-- </el-tooltip>-->
|
||||
<!-- </div>-->
|
||||
<!-- </template>-->
|
||||
<!-- <el-switch v-model="diyStore.editComponent.field.privacyProtection" />-->
|
||||
<!-- <div class="text-sm text-gray-400">{{ t('提交后自动隐藏文本,仅管理员可查看') }}</div>-->
|
||||
<!-- </el-form-item>-->
|
||||
</el-form>
|
||||
<!-- 表单组件 其他设置 -->
|
||||
<slot name="other"></slot>
|
||||
<el-form label-width="100px" class="px-[10px]">
|
||||
<el-form-item>
|
||||
<template #label>
|
||||
<div class="flex items-center">
|
||||
<span class="mr-[3px]">{{ t('preventDuplication') }}</span>
|
||||
<el-tooltip effect="light" placement="top">
|
||||
<template #content>
|
||||
<p>{{ t('preventDuplicationTipsOne') }}</p>
|
||||
<p>{{ t('preventDuplicationTipsTwo') }}</p>
|
||||
</template>
|
||||
<el-icon>
|
||||
<QuestionFilled color="#999999" />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<el-switch v-model="diyStore.editComponent.field.unique" />
|
||||
</el-form-item>
|
||||
<!-- <el-form-item class="display-block">-->
|
||||
<!-- <template #label>-->
|
||||
<!-- <div class="flex items-center">-->
|
||||
<!-- <span class="mr-[3px]">{{ t('隐私保护') }}</span>-->
|
||||
<!-- <el-tooltip effect="light" placement="top">-->
|
||||
<!-- <template #content>-->
|
||||
<!-- <p>会自动将提交的个人信息做加密展示。</p>-->
|
||||
<!-- <p>适用于公开展示收集的数据且不暴露用户隐私。</p>-->
|
||||
<!-- </template>-->
|
||||
<!-- <el-icon>-->
|
||||
<!-- <QuestionFilled color="#999999" />-->
|
||||
<!-- </el-icon>-->
|
||||
<!-- </el-tooltip>-->
|
||||
<!-- </div>-->
|
||||
<!-- </template>-->
|
||||
<!-- <el-switch v-model="diyStore.editComponent.field.privacyProtection" />-->
|
||||
<!-- <div class="text-sm text-gray-400">{{ t('提交后自动隐藏文本,仅管理员可查看') }}</div>-->
|
||||
<!-- </el-form-item>-->
|
||||
</el-form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
|
||||
<!-- 表单组件 字段样式 -->
|
||||
<slot name="style-field"></slot>
|
||||
<!-- 表单组件 字段样式 -->
|
||||
<slot name="style-field"></slot>
|
||||
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
@ -87,9 +87,9 @@ diyStore.editComponent.ignore = ['componentBgUrl'] // 忽略公共属性
|
||||
|
||||
// 组件验证
|
||||
diyStore.editComponent.verify = (index: number) => {
|
||||
const res = { code: true, message: '' }
|
||||
// todo 只需要考虑该组件自身的验证
|
||||
return res
|
||||
const res = { code: true, message: '' }
|
||||
// todo 只需要考虑该组件自身的验证
|
||||
return res
|
||||
}
|
||||
|
||||
defineExpose({})
|
||||
|
||||
@ -1,53 +1,53 @@
|
||||
<template>
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
|
||||
<!-- 表单组件 字段内容设置 -->
|
||||
<slot name="field"></slot>
|
||||
<el-form label-width="100px" class="px-[10px]">
|
||||
<el-form-item :label="t('access')">
|
||||
<el-radio-group v-model="diyStore.editComponent.mode">
|
||||
<el-radio class="!mr-[20px]" label="authorized_wechat_location">{{ t('authorizeWeChatLocation') }}</el-radio>
|
||||
<el-radio label="open_choose_location">{{ t('manuallySelectPositioning') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<!-- 表单组件 字段内容设置 -->
|
||||
<slot name="field"></slot>
|
||||
<el-form label-width="100px" class="px-[10px]">
|
||||
<el-form-item :label="t('access')">
|
||||
<el-radio-group v-model="diyStore.editComponent.mode">
|
||||
<el-radio class="!mr-[20px]" label="authorized_wechat_location">{{ t('authorizeWeChatLocation') }}</el-radio>
|
||||
<el-radio label="open_choose_location">{{ t('manuallySelectPositioning') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 表单组件 其他设置 -->
|
||||
<slot name="other"></slot>
|
||||
<el-form label-width="100px" class="px-[10px]">
|
||||
<el-form-item class="display-block">
|
||||
<template #label>
|
||||
<div class="flex items-center">
|
||||
<span class="mr-[3px]">{{ t('privacyProtection') }}</span>
|
||||
<el-tooltip effect="light" placement="top">
|
||||
<template #content>
|
||||
<p>{{ t('privacyProtectionTipsOne') }}</p>
|
||||
<p>{{ t('privacyProtectionTipsTwo') }}</p>
|
||||
</template>
|
||||
<el-icon>
|
||||
<QuestionFilled color="#999999" />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<el-switch v-model="diyStore.editComponent.field.privacyProtection" />
|
||||
<div class="text-sm text-gray-400">{{ t('privacyProtectionTipsFour') }}</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<!-- 表单组件 其他设置 -->
|
||||
<slot name="other"></slot>
|
||||
<el-form label-width="100px" class="px-[10px]">
|
||||
<el-form-item class="display-block">
|
||||
<template #label>
|
||||
<div class="flex items-center">
|
||||
<span class="mr-[3px]">{{ t('privacyProtection') }}</span>
|
||||
<el-tooltip effect="light" placement="top">
|
||||
<template #content>
|
||||
<p>{{ t('privacyProtectionTipsOne') }}</p>
|
||||
<p>{{ t('privacyProtectionTipsTwo') }}</p>
|
||||
</template>
|
||||
<el-icon>
|
||||
<QuestionFilled color="#999999" />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<el-switch v-model="diyStore.editComponent.field.privacyProtection" />
|
||||
<div class="text-sm text-gray-400">{{ t('privacyProtectionTipsFour') }}</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
|
||||
<!-- 表单组件 字段样式 -->
|
||||
<slot name="style-field"></slot>
|
||||
<!-- 表单组件 字段样式 -->
|
||||
<slot name="style-field"></slot>
|
||||
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
@ -61,7 +61,7 @@ diyStore.editComponent.ignore = ['componentBgUrl'] // 忽略公共属性
|
||||
// 组件验证
|
||||
diyStore.editComponent.verify = (index: number) => {
|
||||
const res = { code: true, message: '' }
|
||||
// todo 只需要考虑该组件自身的验证
|
||||
// todo 只需要考虑该组件自身的验证
|
||||
return res
|
||||
}
|
||||
defineExpose({})
|
||||
|
||||
@ -1,67 +1,67 @@
|
||||
<template>
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
|
||||
<!-- 表单组件 字段内容设置 -->
|
||||
<slot name="field"></slot>
|
||||
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
|
||||
<el-form-item :label="t('formPlaceholder')">
|
||||
<el-input v-model.trim="diyStore.editComponent.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<!-- 表单组件 字段内容设置 -->
|
||||
<slot name="field"></slot>
|
||||
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
|
||||
<el-form-item :label="t('formPlaceholder')">
|
||||
<el-input v-model.trim="diyStore.editComponent.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 表单组件 其他设置 -->
|
||||
<slot name="other"></slot>
|
||||
<el-form label-width="100px" class="px-[10px]">
|
||||
<el-form-item>
|
||||
<template #label>
|
||||
<div class="flex items-center">
|
||||
<span class="mr-[3px]">{{ t('preventDuplication') }}</span>
|
||||
<el-tooltip effect="light" placement="top">
|
||||
<template #content>
|
||||
<p>{{ t('preventDuplicationTipsOne') }}</p>
|
||||
<p>{{ t('preventDuplicationTipsTwo') }}</p>
|
||||
</template>
|
||||
<el-icon>
|
||||
<QuestionFilled color="#999999" />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<el-switch v-model="diyStore.editComponent.field.unique" />
|
||||
</el-form-item>
|
||||
<el-form-item class="display-block">
|
||||
<template #label>
|
||||
<div class="flex items-center">
|
||||
<span class="mr-[3px]">{{ t('privacyProtection') }}</span>
|
||||
<el-tooltip effect="light" placement="top">
|
||||
<template #content>
|
||||
<p>{{ t('privacyProtectionTipsOne') }}</p>
|
||||
<p>{{ t('privacyProtectionTipsTwo') }}</p>
|
||||
</template>
|
||||
<el-icon>
|
||||
<QuestionFilled color="#999999" />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<el-switch v-model="diyStore.editComponent.field.privacyProtection" />
|
||||
<div class="text-sm text-gray-400">{{ t('privacyProtectionTipsFive') }}</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<!-- 表单组件 其他设置 -->
|
||||
<slot name="other"></slot>
|
||||
<el-form label-width="100px" class="px-[10px]">
|
||||
<el-form-item>
|
||||
<template #label>
|
||||
<div class="flex items-center">
|
||||
<span class="mr-[3px]">{{ t('preventDuplication') }}</span>
|
||||
<el-tooltip effect="light" placement="top">
|
||||
<template #content>
|
||||
<p>{{ t('preventDuplicationTipsOne') }}</p>
|
||||
<p>{{ t('preventDuplicationTipsTwo') }}</p>
|
||||
</template>
|
||||
<el-icon>
|
||||
<QuestionFilled color="#999999" />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<el-switch v-model="diyStore.editComponent.field.unique" />
|
||||
</el-form-item>
|
||||
<el-form-item class="display-block">
|
||||
<template #label>
|
||||
<div class="flex items-center">
|
||||
<span class="mr-[3px]">{{ t('privacyProtection') }}</span>
|
||||
<el-tooltip effect="light" placement="top">
|
||||
<template #content>
|
||||
<p>{{ t('privacyProtectionTipsOne') }}</p>
|
||||
<p>{{ t('privacyProtectionTipsTwo') }}</p>
|
||||
</template>
|
||||
<el-icon>
|
||||
<QuestionFilled color="#999999" />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<el-switch v-model="diyStore.editComponent.field.privacyProtection" />
|
||||
<div class="text-sm text-gray-400">{{ t('privacyProtectionTipsFive') }}</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
|
||||
<!-- 表单组件 字段样式 -->
|
||||
<slot name="style-field"></slot>
|
||||
<!-- 表单组件 字段样式 -->
|
||||
<slot name="style-field"></slot>
|
||||
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
@ -75,7 +75,7 @@ diyStore.editComponent.ignore = ['componentBgUrl'] // 忽略公共属性
|
||||
// 组件验证
|
||||
diyStore.editComponent.verify = (index: number) => {
|
||||
const res = { code: true, message: '' }
|
||||
// todo 只需要考虑该组件自身的验证
|
||||
// todo 只需要考虑该组件自身的验证
|
||||
return res
|
||||
}
|
||||
defineExpose({})
|
||||
|
||||
@ -1,83 +1,83 @@
|
||||
<template>
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
|
||||
<!-- 表单组件 字段内容设置 -->
|
||||
<slot name="field"></slot>
|
||||
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
|
||||
<el-form-item :label="t('formPlaceholder')">
|
||||
<el-input v-model.trim="diyStore.editComponent.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
|
||||
</el-form-item>
|
||||
<!-- 表单组件 字段内容设置 -->
|
||||
<slot name="field"></slot>
|
||||
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
|
||||
<el-form-item :label="t('formPlaceholder')">
|
||||
<el-input v-model.trim="diyStore.editComponent.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('unit')">
|
||||
<el-input v-model.trim="diyStore.editComponent.unit" :placeholder="t('unitPlaceholder')" clearable maxlength="5" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template #label>
|
||||
<div class="flex items-center">
|
||||
<span class="mr-[3px]">{{ t('defaultValue') }}</span>
|
||||
<el-tooltip effect="light" :content="t('defaultValueTips')" placement="top">
|
||||
<el-icon>
|
||||
<QuestionFilled color="#999999" />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<el-input v-model.trim="diyStore.editComponent.field.default" :placeholder="t('defaultValuePlaceholder')" @keyup="filterDigit($event)" clearable maxlength="18" show-word-limit />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-input v-model.trim="diyStore.editComponent.unit" :placeholder="t('unitPlaceholder')" clearable maxlength="5" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template #label>
|
||||
<div class="flex items-center">
|
||||
<span class="mr-[3px]">{{ t('defaultValue') }}</span>
|
||||
<el-tooltip effect="light" :content="t('defaultValueTips')" placement="top">
|
||||
<el-icon>
|
||||
<QuestionFilled color="#999999" />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<el-input v-model.trim="diyStore.editComponent.field.default" :placeholder="t('defaultValuePlaceholder')" @keyup="filterDigit($event)" clearable maxlength="18" show-word-limit />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 表单组件 其他设置 -->
|
||||
<slot name="other"></slot>
|
||||
<el-form label-width="100px" class="px-[10px]">
|
||||
<!-- <el-form-item>-->
|
||||
<!-- <template #label>-->
|
||||
<!-- <div class="flex items-center">-->
|
||||
<!-- <span class="mr-[3px]">{{ t('内容防重复') }}</span>-->
|
||||
<!-- <el-tooltip effect="light" placement="top">-->
|
||||
<!-- <template #content>-->
|
||||
<!-- <p>该组件填写的内容不能与已提交的数据重复。</p>-->
|
||||
<!-- <p>极端情况下可能存在延时导致限制失效。</p>-->
|
||||
<!-- </template>-->
|
||||
<!-- <el-icon>-->
|
||||
<!-- <QuestionFilled color="#999999" />-->
|
||||
<!-- </el-icon>-->
|
||||
<!-- </el-tooltip>-->
|
||||
<!-- </div>-->
|
||||
<!-- </template>-->
|
||||
<!-- <el-switch v-model="diyStore.editComponent.field.unique" />-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- <el-form-item class="display-block">-->
|
||||
<!-- <template #label>-->
|
||||
<!-- <div class="flex items-center">-->
|
||||
<!-- <span class="mr-[3px]">{{ t('隐私保护') }}</span>-->
|
||||
<!-- <el-tooltip effect="light" placement="top">-->
|
||||
<!-- <template #content>-->
|
||||
<!-- <p>会自动将提交的个人信息做加密展示。</p>-->
|
||||
<!-- <p>适用于公开展示收集的数据且不暴露用户隐私。</p>-->
|
||||
<!-- </template>-->
|
||||
<!-- <el-icon>-->
|
||||
<!-- <QuestionFilled color="#999999" />-->
|
||||
<!-- </el-icon>-->
|
||||
<!-- </el-tooltip>-->
|
||||
<!-- </div>-->
|
||||
<!-- </template>-->
|
||||
<!-- <el-switch v-model="diyStore.editComponent.field.privacyProtection" />-->
|
||||
<!-- <div class="text-sm text-gray-400">{{ t('提交后自动隐藏数字,仅管理员可查看') }}</div>-->
|
||||
<!-- </el-form-item>-->
|
||||
</el-form>
|
||||
<!-- 表单组件 其他设置 -->
|
||||
<slot name="other"></slot>
|
||||
<el-form label-width="100px" class="px-[10px]">
|
||||
<!-- <el-form-item>-->
|
||||
<!-- <template #label>-->
|
||||
<!-- <div class="flex items-center">-->
|
||||
<!-- <span class="mr-[3px]">{{ t('内容防重复') }}</span>-->
|
||||
<!-- <el-tooltip effect="light" placement="top">-->
|
||||
<!-- <template #content>-->
|
||||
<!-- <p>该组件填写的内容不能与已提交的数据重复。</p>-->
|
||||
<!-- <p>极端情况下可能存在延时导致限制失效。</p>-->
|
||||
<!-- </template>-->
|
||||
<!-- <el-icon>-->
|
||||
<!-- <QuestionFilled color="#999999" />-->
|
||||
<!-- </el-icon>-->
|
||||
<!-- </el-tooltip>-->
|
||||
<!-- </div>-->
|
||||
<!-- </template>-->
|
||||
<!-- <el-switch v-model="diyStore.editComponent.field.unique" />-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- <el-form-item class="display-block">-->
|
||||
<!-- <template #label>-->
|
||||
<!-- <div class="flex items-center">-->
|
||||
<!-- <span class="mr-[3px]">{{ t('隐私保护') }}</span>-->
|
||||
<!-- <el-tooltip effect="light" placement="top">-->
|
||||
<!-- <template #content>-->
|
||||
<!-- <p>会自动将提交的个人信息做加密展示。</p>-->
|
||||
<!-- <p>适用于公开展示收集的数据且不暴露用户隐私。</p>-->
|
||||
<!-- </template>-->
|
||||
<!-- <el-icon>-->
|
||||
<!-- <QuestionFilled color="#999999" />-->
|
||||
<!-- </el-icon>-->
|
||||
<!-- </el-tooltip>-->
|
||||
<!-- </div>-->
|
||||
<!-- </template>-->
|
||||
<!-- <el-switch v-model="diyStore.editComponent.field.privacyProtection" />-->
|
||||
<!-- <div class="text-sm text-gray-400">{{ t('提交后自动隐藏数字,仅管理员可查看') }}</div>-->
|
||||
<!-- </el-form-item>-->
|
||||
</el-form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
|
||||
<!-- 表单组件 字段样式 -->
|
||||
<slot name="style-field"></slot>
|
||||
<!-- 表单组件 字段样式 -->
|
||||
<slot name="style-field"></slot>
|
||||
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
@ -92,24 +92,24 @@ diyStore.editComponent.ignore = ['componentBgUrl'] // 忽略公共属性
|
||||
// 组件验证
|
||||
diyStore.editComponent.verify = (index: number) => {
|
||||
const res = { code: true, message: '' }
|
||||
if(diyStore.value[index].field.default){
|
||||
if (isNaN(diyStore.value[index].field.default) || !regExp.digit.test(diyStore.value[index].field.default)) {
|
||||
res.code = false;
|
||||
res.message = t('defaultErrorTips');
|
||||
} else if (diyStore.value[index].field.default < 0) {
|
||||
res.code = false;
|
||||
res.message = t('defaultMustZeroTips')
|
||||
}
|
||||
}
|
||||
return res
|
||||
if (diyStore.value[index].field.default) {
|
||||
if (isNaN(diyStore.value[index].field.default) || !regExp.digit.test(diyStore.value[index].field.default)) {
|
||||
res.code = false;
|
||||
res.message = t('defaultErrorTips');
|
||||
} else if (diyStore.value[index].field.default < 0) {
|
||||
res.code = false;
|
||||
res.message = t('defaultMustZeroTips')
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// 正则表达式
|
||||
const regExp: any = {
|
||||
required: /[\S]+/,
|
||||
number: /^\d{0,10}$/,
|
||||
digit: /^\d{0,10}(.?\d{0,2})$/,
|
||||
special: /^\d{0,10}(.?\d{0,3})$/
|
||||
required: /[\S]+/,
|
||||
number: /^\d{0,10}$/,
|
||||
digit: /^\d{0,10}(.?\d{0,2})$/,
|
||||
special: /^\d{0,10}(.?\d{0,3})$/
|
||||
}
|
||||
|
||||
defineExpose({})
|
||||
|
||||
@ -1,189 +1,189 @@
|
||||
<template>
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
|
||||
<!-- 表单组件 字段内容设置 -->
|
||||
<slot name="field"></slot>
|
||||
<el-form label-width="100px" class="px-[10px]">
|
||||
<el-form-item :label="t('style')">
|
||||
<el-radio-group v-model="diyStore.editComponent.style">
|
||||
<el-radio label="style-1">{{ t('defaultSources') }}</el-radio>
|
||||
<el-radio label="style-2">{{ t('listStyle') }}</el-radio>
|
||||
<el-radio label="style-3">{{ t('dropDownStyle') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('option')">
|
||||
<!-- 表单组件 字段内容设置 -->
|
||||
<slot name="field"></slot>
|
||||
<el-form label-width="100px" class="px-[10px]">
|
||||
<el-form-item :label="t('style')">
|
||||
<el-radio-group v-model="diyStore.editComponent.style">
|
||||
<el-radio label="style-1">{{ t('defaultSources') }}</el-radio>
|
||||
<el-radio label="style-2">{{ t('listStyle') }}</el-radio>
|
||||
<el-radio label="style-3">{{ t('dropDownStyle') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('option')">
|
||||
<div ref="formRadioRef">
|
||||
<div v-for="(option, index) in diyStore.editComponent.options" :key="option.id" class="option-item flex items-center mb-[15px]">
|
||||
<el-input v-model="diyStore.editComponent.options[index].text" class="!w-[215px]" :placeholder="t('optionPlaceholder')" clearable maxlength="30" />
|
||||
<span v-if="diyStore.editComponent.options.length > 1" @click="removeOption(index)" class="cursor-pointer ml-[5px] nc-iconfont nc-icon-shanchu-yuangaizhiV6xx"></span>
|
||||
</div>
|
||||
</div>
|
||||
<span class="text-primary cursor-pointer mr-[10px]" @click="addOption">{{ t('addSingleOption') }}</span>
|
||||
<el-popover :visible="visible" placement="bottom" :width="300">
|
||||
<p class="mb-[5px]">{{ t('addMultipleOption') }}</p>
|
||||
<p class="text-[#888] text-[12px] mb-[5px]">{{ t('addOptionTips') }}</p>
|
||||
<el-input v-model.trim="optionsValue" type="textarea" clearable maxlength="200" show-word-limit />
|
||||
<div class="mt-[10px] text-right">
|
||||
<el-button size="small" text @click="visible = false">{{ t('cancel') }}</el-button>
|
||||
<el-button size="small" type="primary" @click="batchAddOptions">{{ t('confirm') }}</el-button>
|
||||
</div>
|
||||
<template #reference>
|
||||
<span class="text-primary cursor-pointer" @click="visible = true">{{ t('addMultipleOption') }}</span>
|
||||
</template>
|
||||
</el-popover>
|
||||
</el-form-item>
|
||||
<!-- <el-form-item class="display-block">
|
||||
<template #label>
|
||||
<div class="flex items-center">
|
||||
<span class="mr-[3px]">{{ t('逻辑规则') }}</span>
|
||||
<el-tooltip effect="light" placement="top">
|
||||
<template #content>
|
||||
<p>支持选择某个选项后,显示特定的组件。</p>
|
||||
</template>
|
||||
<el-icon>
|
||||
<QuestionFilled color="#999999" />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<div>
|
||||
<el-button plain>{{ t('添加字段显示规则') }}</el-button>
|
||||
<span class="mr-[3px]">1条字段显示规则</span>
|
||||
<span class="text-primary cursor-pointer" @click="">设置</span>
|
||||
</div>
|
||||
</el-form-item> -->
|
||||
</el-form>
|
||||
<span class="text-primary cursor-pointer mr-[10px]" @click="addOption">{{ t('addSingleOption') }}</span>
|
||||
<el-popover :visible="visible" placement="bottom" :width="300">
|
||||
<p class="mb-[5px]">{{ t('addMultipleOption') }}</p>
|
||||
<p class="text-[#888] text-[12px] mb-[5px]">{{ t('addOptionTips') }}</p>
|
||||
<el-input v-model.trim="optionsValue" type="textarea" clearable maxlength="200" show-word-limit />
|
||||
<div class="mt-[10px] text-right">
|
||||
<el-button size="small" text @click="visible = false">{{ t('cancel') }}</el-button>
|
||||
<el-button size="small" type="primary" @click="batchAddOptions">{{ t('confirm') }}</el-button>
|
||||
</div>
|
||||
<template #reference>
|
||||
<span class="text-primary cursor-pointer" @click="visible = true">{{ t('addMultipleOption') }}</span>
|
||||
</template>
|
||||
</el-popover>
|
||||
</el-form-item>
|
||||
<!-- <el-form-item class="display-block">
|
||||
<template #label>
|
||||
<div class="flex items-center">
|
||||
<span class="mr-[3px]">{{ t('逻辑规则') }}</span>
|
||||
<el-tooltip effect="light" placement="top">
|
||||
<template #content>
|
||||
<p>支持选择某个选项后,显示特定的组件。</p>
|
||||
</template>
|
||||
<el-icon>
|
||||
<QuestionFilled color="#999999" />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<div>
|
||||
<el-button plain>{{ t('添加字段显示规则') }}</el-button>
|
||||
<span class="mr-[3px]">1条字段显示规则</span>
|
||||
<span class="text-primary cursor-pointer" @click="">设置</span>
|
||||
</div>
|
||||
</el-form-item> -->
|
||||
</el-form>
|
||||
|
||||
<!-- 表单组件 其他设置 -->
|
||||
<slot name="other"></slot>
|
||||
<!-- <el-form label-width="100px" class="px-[10px]">-->
|
||||
<!-- <el-form-item class="display-block">-->
|
||||
<!-- <template #label>-->
|
||||
<!-- <div class="flex items-center">-->
|
||||
<!-- <span class="mr-[3px]">{{ t('隐私保护') }}</span>-->
|
||||
<!-- <el-tooltip effect="light" placement="top">-->
|
||||
<!-- <template #content>-->
|
||||
<!-- <p>会自动将提交的个人信息做加密展示。</p>-->
|
||||
<!-- <p>适用于公开展示收集的数据且不暴露用户隐私。</p>-->
|
||||
<!-- </template>-->
|
||||
<!-- <el-icon>-->
|
||||
<!-- <QuestionFilled color="#999999" />-->
|
||||
<!-- </el-icon>-->
|
||||
<!-- </el-tooltip>-->
|
||||
<!-- </div>-->
|
||||
<!-- </template>-->
|
||||
<!-- <el-switch v-model="diyStore.editComponent.field.privacyProtection" />-->
|
||||
<!-- <div class="text-sm text-gray-400">{{ t('提交后自动隐藏内容,仅管理员可查看') }}</div>-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- 表单组件 其他设置 -->
|
||||
<slot name="other"></slot>
|
||||
<!-- <el-form label-width="100px" class="px-[10px]">-->
|
||||
<!-- <el-form-item class="display-block">-->
|
||||
<!-- <template #label>-->
|
||||
<!-- <div class="flex items-center">-->
|
||||
<!-- <span class="mr-[3px]">{{ t('隐私保护') }}</span>-->
|
||||
<!-- <el-tooltip effect="light" placement="top">-->
|
||||
<!-- <template #content>-->
|
||||
<!-- <p>会自动将提交的个人信息做加密展示。</p>-->
|
||||
<!-- <p>适用于公开展示收集的数据且不暴露用户隐私。</p>-->
|
||||
<!-- </template>-->
|
||||
<!-- <el-icon>-->
|
||||
<!-- <QuestionFilled color="#999999" />-->
|
||||
<!-- </el-icon>-->
|
||||
<!-- </el-tooltip>-->
|
||||
<!-- </div>-->
|
||||
<!-- </template>-->
|
||||
<!-- <el-switch v-model="diyStore.editComponent.field.privacyProtection" />-->
|
||||
<!-- <div class="text-sm text-gray-400">{{ t('提交后自动隐藏内容,仅管理员可查看') }}</div>-->
|
||||
<!-- </el-form-item>-->
|
||||
|
||||
<!-- </el-form>-->
|
||||
<!-- </el-form>-->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
|
||||
<!-- 表单组件 字段样式 -->
|
||||
<slot name="style-field"></slot>
|
||||
<!-- 表单组件 字段样式 -->
|
||||
<slot name="style-field"></slot>
|
||||
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { t } from '@/lang'
|
||||
import { ref, onMounted, nextTick} from 'vue'
|
||||
import { ref, onMounted, nextTick } from 'vue'
|
||||
import useDiyStore from '@/stores/modules/diy'
|
||||
import Sortable from 'sortablejs'
|
||||
import { range } from 'lodash-es'
|
||||
import { FormInstance, ElMessage } from "element-plus";
|
||||
import { ElMessage } from "element-plus";
|
||||
|
||||
const diyStore = useDiyStore()
|
||||
diyStore.editComponent.ignore = ['componentBgUrl'] // 忽略公共属性
|
||||
|
||||
// 组件验证
|
||||
diyStore.editComponent.verify = (index: number) => {
|
||||
const res = { code: true, message: '' }
|
||||
let pass = true;
|
||||
for (let i = 0; i < diyStore.value[index].options.length; i++) {
|
||||
if (!diyStore.value[index].options[i].text) {
|
||||
res.code = false;
|
||||
res.message = t('optionPlaceholder');
|
||||
pass = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
const res = { code: true, message: '' }
|
||||
let pass = true;
|
||||
for (let i = 0; i < diyStore.value[index].options.length; i++) {
|
||||
if (!diyStore.value[index].options[i].text) {
|
||||
res.code = false;
|
||||
res.message = t('optionPlaceholder');
|
||||
pass = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!pass) return res;
|
||||
if (!pass) return res;
|
||||
|
||||
let uniqueOptions = uniqueByKey(diyStore.value[index].options, 'text')
|
||||
let uniqueOptions = uniqueByKey(diyStore.value[index].options, 'text')
|
||||
|
||||
if (uniqueOptions.length != diyStore.value[index].options.length) {
|
||||
res.code = false;
|
||||
res.message = t('errorTipsOne')
|
||||
}
|
||||
return res
|
||||
if (uniqueOptions.length != diyStore.value[index].options.length) {
|
||||
res.code = false;
|
||||
res.message = t('errorTipsOne')
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
diyStore.editComponent.options.forEach((item: any) => {
|
||||
if (!item.id) item.id = diyStore.generateRandom()
|
||||
if (!item.id) item.id = diyStore.generateRandom()
|
||||
})
|
||||
|
||||
const visible = ref(false)
|
||||
const optionsValue = ref()
|
||||
const addOption = () => {
|
||||
diyStore.editComponent.options.push({
|
||||
id: diyStore.generateRandom(),
|
||||
text: '选项' + (diyStore.editComponent.options.length + 1)
|
||||
});
|
||||
diyStore.editComponent.options.push({
|
||||
id: diyStore.generateRandom(),
|
||||
text: '选项' + (diyStore.editComponent.options.length + 1)
|
||||
});
|
||||
};
|
||||
|
||||
const removeOption = (index:any) => {
|
||||
const removeOption = (index: any) => {
|
||||
diyStore.editComponent.options.splice(index, 1);
|
||||
}
|
||||
|
||||
const batchAddOptions = () => {
|
||||
if (optionsValue.value.trim()) {
|
||||
const newOptions = optionsValue.value.split(',').map((option: any) => {
|
||||
return {
|
||||
id: diyStore.generateRandom(),
|
||||
text: option.trim()
|
||||
};
|
||||
}).filter((option: any) => option.text !== '');
|
||||
if (optionsValue.value.trim()) {
|
||||
const newOptions = optionsValue.value.split(',').map((option: any) => {
|
||||
return {
|
||||
id: diyStore.generateRandom(),
|
||||
text: option.trim()
|
||||
};
|
||||
}).filter((option: any) => option.text !== '');
|
||||
|
||||
// 去除重复的选项
|
||||
const uniqueNewOptions = uniqueByKey(newOptions, 'text');
|
||||
// 去除重复的选项
|
||||
const uniqueNewOptions = uniqueByKey(newOptions, 'text');
|
||||
|
||||
// 过滤掉已存在的选项
|
||||
const filteredNewOptions = uniqueNewOptions.filter(newOption =>
|
||||
!diyStore.editComponent.options.some(existingOption => existingOption.text === newOption.text)
|
||||
);
|
||||
// 过滤掉已存在的选项
|
||||
const filteredNewOptions = uniqueNewOptions.filter(newOption =>
|
||||
!diyStore.editComponent.options.some(existingOption => existingOption.text === newOption.text)
|
||||
);
|
||||
|
||||
// 如果有新的选项,添加到选项列表中
|
||||
if (filteredNewOptions.length > 0) {
|
||||
diyStore.editComponent.options.push(...filteredNewOptions);
|
||||
} else {
|
||||
ElMessage({
|
||||
message: t('errorTipsTwo'),
|
||||
type: "warning",
|
||||
});
|
||||
}
|
||||
// 如果有新的选项,添加到选项列表中
|
||||
if (filteredNewOptions.length > 0) {
|
||||
diyStore.editComponent.options.push(...filteredNewOptions);
|
||||
} else {
|
||||
ElMessage({
|
||||
message: t('errorTipsTwo'),
|
||||
type: "warning",
|
||||
});
|
||||
}
|
||||
|
||||
optionsValue.value = '';
|
||||
visible.value = false;
|
||||
}
|
||||
optionsValue.value = '';
|
||||
visible.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 数组去重
|
||||
const uniqueByKey = (arr: any, key: any) => {
|
||||
const seen = new Set();
|
||||
return arr.filter((item: any) => {
|
||||
const serializedKey = JSON.stringify(item[key]);
|
||||
return seen.has(serializedKey) ? false : seen.add(serializedKey);
|
||||
});
|
||||
const seen = new Set();
|
||||
return arr.filter((item: any) => {
|
||||
const serializedKey = JSON.stringify(item[key]);
|
||||
return seen.has(serializedKey) ? false : seen.add(serializedKey);
|
||||
});
|
||||
}
|
||||
|
||||
const formRadioRef = ref()
|
||||
|
||||
@ -1,75 +1,79 @@
|
||||
<template>
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
<div class="edit-attr-item-wrap">
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
<div class="edit-attr-item-wrap">
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('floatBtnButton')" class="display-block">
|
||||
<el-radio-group v-model="diyStore.editComponent.btnPosition" @change="btnPositionChangeFn">
|
||||
<el-radio label="follow_content">{{ t('followContent') }}</el-radio>
|
||||
<el-radio label="hover_screen_bottom">{{ t('hoverScreenBottom') }}</el-radio>
|
||||
</el-radio-group>
|
||||
<div class="text-sm text-gray-400 mb-[5px] leading-[1.4]" v-show="diyStore.editComponent.btnPosition == 'follow_content'">{{ t('btnTips') }}</div>
|
||||
<div class="text-sm text-gray-400 mb-[5px]" v-show="diyStore.editComponent.btnPosition == 'hover_screen_bottom'">{{ t('btnTipsTwo') }}</div>
|
||||
<el-form-item :label="t('floatBtnButton')" class="display-block">
|
||||
<el-radio-group v-model="diyStore.editComponent.btnPosition" @change="btnPositionChangeFn">
|
||||
<el-radio label="follow_content">{{ t('followContent') }}</el-radio>
|
||||
<el-radio label="hover_screen_bottom">{{ t('hoverScreenBottom') }}</el-radio>
|
||||
</el-radio-group>
|
||||
<div class="text-sm text-gray-400 mb-[5px] leading-[1.4]"
|
||||
v-show="diyStore.editComponent.btnPosition == 'follow_content'">{{ t('btnTips') }}
|
||||
</div>
|
||||
<div class="text-sm text-gray-400 mb-[5px]"
|
||||
v-show="diyStore.editComponent.btnPosition == 'hover_screen_bottom'">{{ t('btnTipsTwo') }}
|
||||
</div>
|
||||
<div class="text-sm text-gray-400 mb-[10px] leading-[1.4]">{{ t('btnTipsThree') }}</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('submitBtn') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]" @submit.prevent>
|
||||
<el-form-item :label="t('submitBtnName')">
|
||||
<el-input v-model.trim="diyStore.editComponent.submitBtn.text" :placeholder="t('btnNamePlaceholder')" clearable maxlength="10" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('textColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.submitBtn.color" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('subTextBgColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.submitBtn.bgColor" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('submitBtn') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]" @submit.prevent>
|
||||
<el-form-item :label="t('submitBtnName')">
|
||||
<el-input v-model.trim="diyStore.editComponent.submitBtn.text" :placeholder="t('btnNamePlaceholder')" clearable maxlength="10" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('textColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.submitBtn.color" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('subTextBgColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.submitBtn.bgColor" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('resetBtn') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]" @submit.prevent>
|
||||
<el-form-item :label="t('carouselSearchTabControl')">
|
||||
<el-switch v-model="diyStore.editComponent.resetBtn.control" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('submitBtnName')">
|
||||
<el-input v-model.trim="diyStore.editComponent.resetBtn.text" :placeholder="t('btnNamePlaceholder')" clearable maxlength="10" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('textColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.resetBtn.color" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('subTextBgColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.resetBtn.bgColor" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('resetBtn') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]" @submit.prevent>
|
||||
<el-form-item :label="t('carouselSearchTabControl')">
|
||||
<el-switch v-model="diyStore.editComponent.resetBtn.control" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('submitBtnName')">
|
||||
<el-input v-model.trim="diyStore.editComponent.resetBtn.text" :placeholder="t('btnNamePlaceholder')" clearable maxlength="10" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('textColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.resetBtn.color" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('subTextBgColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.resetBtn.bgColor" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('btnStyle') }}</h3>
|
||||
<el-form label-width="100px" class="px-[10px]">
|
||||
<el-form-item :label="t('topRounded')">
|
||||
<el-slider v-model="diyStore.editComponent.topElementRounded" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('bottomRounded')">
|
||||
<el-slider v-model="diyStore.editComponent.bottomElementRounded" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('btnStyle') }}</h3>
|
||||
<el-form label-width="100px" class="px-[10px]">
|
||||
<el-form-item :label="t('topRounded')">
|
||||
<el-slider v-model="diyStore.editComponent.topElementRounded" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('bottomRounded')">
|
||||
<el-slider v-model="diyStore.editComponent.bottomElementRounded" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
@ -81,8 +85,8 @@ const diyStore = useDiyStore()
|
||||
diyStore.editComponent.ignore = ['componentBgUrl'] // 忽略公共属性
|
||||
|
||||
// 单选
|
||||
const btnPositionChangeFn = (e)=>{
|
||||
if(e == 'hover_screen_bottom'){
|
||||
const btnPositionChangeFn = (e) => {
|
||||
if (e == 'hover_screen_bottom') {
|
||||
diyStore.editComponent.margin.bottom = 0;
|
||||
diyStore.editComponent.margin.both = 0;
|
||||
diyStore.editComponent.margin.top = 0;
|
||||
@ -91,19 +95,19 @@ const btnPositionChangeFn = (e)=>{
|
||||
|
||||
// 组件验证
|
||||
diyStore.editComponent.verify = (index: number) => {
|
||||
const res = { code: true, message: '' }
|
||||
if (diyStore.value[index].submitBtn.text == '') {
|
||||
res.code = false;
|
||||
res.message = t('submitBtnNamePlaceholder');
|
||||
return res;
|
||||
}
|
||||
if (diyStore.value[index].resetBtn.text == '') {
|
||||
res.code = false;
|
||||
res.message = t('resetBtnNamePlaceholder');
|
||||
return res;
|
||||
}
|
||||
const res = { code: true, message: '' }
|
||||
if (diyStore.value[index].submitBtn.text == '') {
|
||||
res.code = false;
|
||||
res.message = t('submitBtnNamePlaceholder');
|
||||
return res;
|
||||
}
|
||||
if (diyStore.value[index].resetBtn.text == '') {
|
||||
res.code = false;
|
||||
res.message = t('resetBtnNamePlaceholder');
|
||||
return res;
|
||||
}
|
||||
|
||||
return res
|
||||
return res
|
||||
}
|
||||
|
||||
defineExpose({})
|
||||
|
||||
@ -1,44 +1,412 @@
|
||||
<template>
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
|
||||
<!-- 表单组件 字段内容设置 -->
|
||||
<slot name="field"></slot>
|
||||
todo 此处编写表格组件的属性
|
||||
<!-- 表单组件 字段内容设置 -->
|
||||
<slot name="field"></slot>
|
||||
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
|
||||
<el-form-item :label="t('列设置')">
|
||||
<div ref="imageBoxRef">
|
||||
<div v-for="(item, index) in diyStore.editComponent.columnList" :key="item.id"
|
||||
class="border-b-[1px] border-[#e0e0e0] py-1">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex">
|
||||
<span :class="['iconfont', 'ml-[5px]', 'cursor-pointer', getIconClass(item.type)]"></span>
|
||||
<el-input v-model="item.name" class="input-style" :input-style="{ boxShadow: 'none' }"
|
||||
:placeholder="t('请输入列名')" />
|
||||
</div>
|
||||
<div class="flex">
|
||||
<span v-if="diyStore.editComponent.columnList.length > 1" @click="removeOption(index)"
|
||||
class="cursor-pointer ml-[5px] nc-iconfont nc-icon-shanchu-yuangaizhiV6xx"></span>
|
||||
<span class="cursor-pointer ml-[5px] nc-iconfont nc-icon-xiaV6xx"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="item.type == 'radio'" class="flex">
|
||||
<div class="text-[#999] mr-3" >{{ item.options?.length || 0 }}个选项</div>
|
||||
<span class="text-primary cursor-pointer mr-[10px]" @click="openRadioDialog(item, index)">{{ t('编辑') }}</span>
|
||||
</div>
|
||||
<div v-if="item.type == 'date'" class="flex">
|
||||
<span class="text-primary cursor-pointer mr-[10px]" @click="openRadioDialog(item, index)">{{ t('设置日期格式') }}</span>
|
||||
</div>
|
||||
<div v-if="item.type == 'address'" class="flex">
|
||||
<div class="text-[#999] mr-3">精确到详细地址</div>
|
||||
<span class="text-primary cursor-pointer mr-[10px]" @click="openRadioDialog(item, index)">{{ t('设置') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-popover placement="bottom" :width="50" trigger="hover">
|
||||
<template #reference>
|
||||
<span class="text-primary cursor-pointer mr-[10px]">{{ t('添加') }}</span>
|
||||
</template>
|
||||
<div v-for="(item, index) in columnTypeOptions" :key="index" @click="addOption(item)"
|
||||
class="cursor-pointer hover:bg-[#d1e1ff] rounded text-center">
|
||||
<div class="py-1 text-[var(--el-text-color-primary]">{{ item.label }}</div>
|
||||
</div>
|
||||
</el-popover>
|
||||
|
||||
<!-- 表单组件 其他设置 -->
|
||||
<slot name="other"></slot>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('是否自增')">
|
||||
<el-switch v-model="diyStore.editComponent.autoIncrementControl" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('填写限制')" v-if="diyStore.editComponent.autoIncrementControl">
|
||||
<div class="flex items-center">
|
||||
<span>默认显示</span>
|
||||
<el-input v-model="diyStore.editComponent.writeLimit.default" class="input-short" :placeholder="t('')" />
|
||||
<span>项</span>
|
||||
</div>
|
||||
<div class="flex items-center my-1">
|
||||
<span>最少填写</span>
|
||||
<el-input v-model="diyStore.editComponent.writeLimit.min" class="input-short" :placeholder="t('')" />
|
||||
<span>项</span>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<span>最多填写</span>
|
||||
<el-input v-model="diyStore.editComponent.writeLimit.max" class="input-short" :placeholder="t('')" />
|
||||
<span>项</span>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('按钮名称')" v-if="diyStore.editComponent.autoIncrementControl">
|
||||
<el-input v-model="diyStore.editComponent.btnText" :placeholder="t('请输入按钮名称')" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<!-- 单选项 -->
|
||||
<!-- <el-dialog v-model="radioDialogVisible" :title="t('设置单选项')" width="500">
|
||||
<div v-if="activeColumnTemp.type == 'radio'">
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('选项名称')">
|
||||
<el-input v-model="activeColumnTemp.name" :input-style="{ boxShadow: 'none' }" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('设置选项')">
|
||||
<div ref="radioBoxRef">
|
||||
<div v-for="(opt, idx) in activeColumnTemp.options" :key="opt.id">
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<div class="flex-1">
|
||||
<el-input v-model="opt.label" :input-style="{ boxShadow: 'none' }"
|
||||
:placeholder="t('请输入')" />
|
||||
</div>
|
||||
<span v-if="activeColumnTemp.options.length > 1" @click="removeOptionItem(idx)"
|
||||
class="cursor-pointer ml-[5px] nc-iconfont nc-icon-shanchu-yuangaizhiV6xx"></span>
|
||||
<span class="cursor-pointer ml-[5px] nc-iconfont nc-icon-iconpaixu1"></span>
|
||||
</div>
|
||||
</div>
|
||||
<span class="text-primary cursor-pointer mr-[10px]" @click="addOptionItem">{{ t('添加选项') }}</span>
|
||||
<span class="text-primary cursor-pointer mr-[10px]" @click="addOtherOption">{{ t('添加其它项') }}</span>
|
||||
<el-popover :visible="visible" placement="bottom" :width="300">
|
||||
<p class="mb-[5px]">{{ t('addMultipleOption') }}</p>
|
||||
<p class="text-[#888] text-[12px] mb-[5px]">{{ t('addOptionTips') }}</p>
|
||||
<el-input v-model.trim="optionsValue" type="textarea" clearable maxlength="200"
|
||||
show-word-limit />
|
||||
<div class="mt-[10px] text-right">
|
||||
<el-button size="small" text @click="visible = false">{{ t('cancel') }}</el-button>
|
||||
<el-button size="small" type="primary" @click="batchAddOptions">{{t('confirm')}}</el-button>
|
||||
</div>
|
||||
<template #reference>
|
||||
<span class="text-primary cursor-pointer"
|
||||
@click="visible = true">{{ t('addMultipleOption') }}</span>
|
||||
</template>
|
||||
</el-popover>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div v-else-if="activeColumnTemp.type == 'date'">
|
||||
<el-form>
|
||||
<el-form-item :label="t('dataFormat')">
|
||||
<el-radio-group v-model="activeColumnTemp.dateFormat" class="!block">
|
||||
<el-radio class="!block" label="YYYY年M月D日">{{ dateFormat.format1 }}</el-radio>
|
||||
<el-radio class="!block" label="YYYY-MM-DD">{{ dateFormat.format2 }}</el-radio>
|
||||
<el-radio class="!block" label="YYYY/MM/DD">{{ dateFormat.format3 }}</el-radio>
|
||||
<el-radio class="!block" label="YYYY-MM-DD HH:mm">{{ dateFormat.format4 }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div v-else-if="activeColumnTemp.type == 'address'">
|
||||
<el-form>
|
||||
<el-form-item :label="t('地址格式')">
|
||||
<el-radio-group v-model="activeColumnTemp.addressFormat" class="!block">
|
||||
<el-radio class="!block" label="province/city/district/address">{{ t('省/市/区/街道/详细地址') }}</el-radio>
|
||||
<el-radio class="!block" label="province/city/district/street">{{ t('省/市/区/街道(镇)') }}</el-radio>
|
||||
<el-radio class="!block" label="province/city/district">{{ t('省/市/区(县)') }}</el-radio>
|
||||
<el-radio class="!block" label="province/city">{{ t('省/市') }}</el-radio>
|
||||
<el-radio class="!block" label="province">{{ t('省') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="radioDialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="handleDialogConfirm">确定</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog> -->
|
||||
|
||||
</div>
|
||||
<div>
|
||||
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
</div>
|
||||
|
||||
<!-- 表单组件 字段样式 -->
|
||||
<slot name="style-field"></slot>
|
||||
<!-- 表单组件 其他设置 -->
|
||||
<slot name="other"></slot>
|
||||
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
|
||||
<!-- 表单组件 字段样式 -->
|
||||
<slot name="style-field"></slot>
|
||||
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { t } from '@/lang'
|
||||
import { ref } from 'vue'
|
||||
import Sortable from 'sortablejs'
|
||||
import { ref, watch, onMounted, nextTick ,reactive, computed} from 'vue'
|
||||
import useDiyStore from '@/stores/modules/diy'
|
||||
|
||||
import { range } from 'lodash-es'
|
||||
const diyStore = useDiyStore()
|
||||
diyStore.editComponent.ignore = ['componentBgUrl'] // 忽略公共属性
|
||||
|
||||
// 组件验证
|
||||
diyStore.editComponent.verify = (index: number) => {
|
||||
const res = { code: true, message: '' }
|
||||
// todo 只需要考虑该组件自身的验证
|
||||
// todo 只需要考虑该组件自身的验证
|
||||
return res
|
||||
}
|
||||
|
||||
// 类型选项数组
|
||||
const columnTypeOptions = ref([
|
||||
{ label: '单选项', value: 'radio' },
|
||||
{ label: '文本', value: 'text' },
|
||||
{ label: '数字', value: 'number' },
|
||||
{ label: '手机号', value: 'mobile' },
|
||||
{ label: '地址', value: 'address' },
|
||||
{ label: '身份证', value: 'idcard' },
|
||||
{ label: '性别', value: 'gender' },
|
||||
{ label: '日期', value: 'date' }
|
||||
])
|
||||
|
||||
const getIconClass = (type:any) => {
|
||||
switch (type) {
|
||||
case 'radio':
|
||||
return 'icona-duihaopc30'
|
||||
case 'text':
|
||||
return 'icona-danhangwenben-1pc30'
|
||||
case 'number':
|
||||
return 'icona-shuzipc30-1'
|
||||
case 'mobile':
|
||||
return 'icona-shoujipc30'
|
||||
case 'address':
|
||||
return 'iconbiaotipc'
|
||||
case 'idcard':
|
||||
return 'icona-shenfenzhengpc30'
|
||||
case 'gender':
|
||||
return 'el-icon-s-opportunity'
|
||||
case 'date':
|
||||
return 'icona-riqipc30'
|
||||
default:
|
||||
return ''
|
||||
}
|
||||
}
|
||||
|
||||
const imageBoxRef = ref()
|
||||
const generateId = () => Date.now().toString(36) + Math.random().toString(36).substr(2, 5)
|
||||
// 添加列方法
|
||||
const addOption = (item) => {
|
||||
const newColumn: any = {
|
||||
id: generateId(),
|
||||
name: item.label,
|
||||
type: item.value, // 列类型
|
||||
value: '' // 默认值(可选)
|
||||
}
|
||||
|
||||
// 如果是单选项,初始化 options
|
||||
if (item.value === 'radio') {
|
||||
newColumn.options = [
|
||||
{ id: generateId(), label: '选项1' },
|
||||
{ id: generateId(), label: '选项2' }
|
||||
]
|
||||
}
|
||||
// 如果是日期,初始化 dateFormat
|
||||
if (item.value === 'date') {
|
||||
newColumn.dateFormat = 'YYYY年M月D日' // 默认日期格式
|
||||
}
|
||||
// 如果是地址,初始化 addressFormat
|
||||
if (item.value === 'address') {
|
||||
newColumn.addressFormat = 'province/city/district/address' // 默认日期格式
|
||||
}
|
||||
|
||||
diyStore.editComponent.columnList.push(newColumn)
|
||||
}
|
||||
|
||||
const removeOption = (index: number) => {
|
||||
diyStore.editComponent.columnList.splice(index, 1)
|
||||
}
|
||||
|
||||
|
||||
onMounted(() => {
|
||||
// nextTick(() => {
|
||||
// if (diyStore.editComponent.columnList.length < 2) return;
|
||||
// const sortable = Sortable.create(imageBoxRef.value, {
|
||||
// group: 'item-wrap',
|
||||
// animation: 200,
|
||||
// onEnd: event => {
|
||||
// const temp = diyStore.editComponent.columnList[event.oldIndex!]
|
||||
// diyStore.editComponent.columnList.splice(event.oldIndex!, 1)
|
||||
// diyStore.editComponent.columnList.splice(event.newIndex!, 0, temp)
|
||||
// sortable.sort(
|
||||
// range(diyStore.editComponent.columnList.length).map(value => {
|
||||
// return value.toString()
|
||||
// })
|
||||
// )
|
||||
// }
|
||||
// })
|
||||
// })
|
||||
console.log(diyStore.editComponent.columnList);
|
||||
|
||||
})
|
||||
|
||||
const activeColumn = ref<any>({}) // 真正数据(原始数据,不动它)
|
||||
const activeColumnTemp = ref<any>({}) // 弹窗编辑临时副本
|
||||
const activeRadioIndex = ref(0) // 当前编辑列的下标
|
||||
|
||||
const radioDialogVisible = ref(false)
|
||||
const radioBoxRef = ref()
|
||||
|
||||
const optionsValue = ref('')
|
||||
const visible = ref(false)
|
||||
const dateFormat: any = reactive({
|
||||
format1: '',
|
||||
format2: '',
|
||||
format3: '',
|
||||
format4: ''
|
||||
});
|
||||
|
||||
const openRadioDialog = (item, index) => {
|
||||
activeRadioIndex.value = index // 记录当前列的下标,方便确定时更新
|
||||
activeColumn.value = item
|
||||
activeColumnTemp.value = JSON.parse(JSON.stringify(item)) // 深拷贝,避免联动
|
||||
if(item.type == 'radio'){
|
||||
if (!activeColumnTemp.value.options) activeColumnTemp.value.options = []
|
||||
radioDialogVisible.value = true
|
||||
// nextTick(() => initRadioSortable()) // 拖拽初始化
|
||||
}else if(item.type == 'date'){
|
||||
// 初始赋值当天日期
|
||||
const today = new Date();
|
||||
let year = today.getFullYear();
|
||||
let month = String(today.getMonth() + 1).padStart(2, '0');
|
||||
let day = String(today.getDate()).padStart(2, '0');
|
||||
|
||||
const hours = String(today.getHours()).padStart(2, '0');
|
||||
const minutes = String(today.getMinutes()).padStart(2, '0');
|
||||
dateFormat.format1 = `${ year }年${ month }月${ day }日`;
|
||||
dateFormat.format2 = `${ year }-${ month }-${ day }`;
|
||||
dateFormat.format3 = `${ year }/${ month }/${ day }`;
|
||||
dateFormat.format4 = `${ year }-${ month }-${ day } ${ hours }:${ minutes }`;
|
||||
radioDialogVisible.value = true
|
||||
} else if(item.type == 'address'){
|
||||
radioDialogVisible.value = true
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化拖拽
|
||||
// const initRadioSortable = () => {
|
||||
// Sortable.create(radioBoxRef.value, {
|
||||
// group: 'radio-option-wrap',
|
||||
// animation: 200,
|
||||
// draggable: '.drag-radio-item',
|
||||
// onEnd: event => {
|
||||
// const options = activeColumnTemp.value.options // 注意!这里用 temp 的
|
||||
// const temp = options[event.oldIndex!]
|
||||
// options.splice(event.oldIndex!, 1)
|
||||
// options.splice(event.newIndex!, 0, temp)
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
|
||||
const handleDialogConfirm = () => {
|
||||
console.log(activeColumnTemp.value);
|
||||
|
||||
diyStore.editComponent.columnList[activeRadioIndex.value] = JSON.parse(JSON.stringify(activeColumnTemp.value)) // 同步副本到原数据
|
||||
radioDialogVisible.value = false // 关闭弹窗
|
||||
}
|
||||
|
||||
const addOptionItem = () => {
|
||||
const newOption = { id: generateId(), label: '选项' + (activeColumnTemp.value.options.length + 1) }
|
||||
activeColumnTemp.value.options.push(newOption)
|
||||
}
|
||||
|
||||
const addOtherOption = () => {
|
||||
const newOption = { id: generateId(), label: '其他' }
|
||||
activeColumnTemp.value.options.push(newOption)
|
||||
}
|
||||
|
||||
const removeOptionItem = (index: number) => {
|
||||
activeColumnTemp.value.options.splice(index, 1)
|
||||
}
|
||||
|
||||
// 数组去重
|
||||
const uniqueByKey = (arr: any, key: any) => {
|
||||
const seen = new Set();
|
||||
return arr.filter((item: any) => {
|
||||
const serializedKey = JSON.stringify(item[key]);
|
||||
return seen.has(serializedKey) ? false : seen.add(serializedKey);
|
||||
});
|
||||
}
|
||||
// 批量添加
|
||||
const batchAddOptions = () => {
|
||||
if (optionsValue.value.trim()) {
|
||||
const newOptions = optionsValue.value.split(',').map((option: any) => {
|
||||
return {
|
||||
id: diyStore.generateRandom(),
|
||||
label: option.trim()
|
||||
};
|
||||
}).filter((option: any) => option.label !== '');
|
||||
|
||||
// 去除重复的选项
|
||||
const uniqueNewOptions = uniqueByKey(newOptions, 'label');
|
||||
|
||||
// 过滤掉已存在的选项
|
||||
const filteredNewOptions = uniqueNewOptions.filter(newOption =>
|
||||
!activeColumnTemp.value.options.some(existingOption => existingOption.label === newOption.label)
|
||||
);
|
||||
|
||||
// 如果有新的选项,添加到选项列表中
|
||||
if (filteredNewOptions.length > 0) {
|
||||
activeColumnTemp.value.options.push(...filteredNewOptions);
|
||||
} else {
|
||||
ElMessage({
|
||||
message: t('errorTipsTwo'),
|
||||
type: "warning",
|
||||
});
|
||||
}
|
||||
|
||||
optionsValue.value = '';
|
||||
visible.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
defineExpose({})
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
<style lang="scss" scoped>
|
||||
:deep(.input-style .el-input__wrapper) {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.input-short{
|
||||
width: 80px;
|
||||
margin: 0 10px;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@ -1,66 +1,67 @@
|
||||
<template>
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
|
||||
<!-- 表单组件 字段内容设置 -->
|
||||
<slot name="field"></slot>
|
||||
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
|
||||
<el-form-item :label="t('formPlaceholder')">
|
||||
<el-input v-model.trim="diyStore.editComponent.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template #label>
|
||||
<div class="flex items-center">
|
||||
<span class="mr-[3px]">{{ t('defaultValue') }}</span>
|
||||
<el-tooltip effect="light" :content="t('defaultValueTips')" placement="top">
|
||||
<el-icon>
|
||||
<QuestionFilled color="#999999" />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<el-input v-model.trim="diyStore.editComponent.field.default" :placeholder="t('defaultValuePlaceholder')" clearable maxlength="18" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('rowCount')">
|
||||
<el-input v-model.trim="diyStore.editComponent.rowCount" :placeholder="t('rowCountPlaceholder')" clearable maxlength="2" show-word-limit />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<!-- 表单组件 字段内容设置 -->
|
||||
<slot name="field"></slot>
|
||||
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
|
||||
<el-form-item :label="t('formPlaceholder')">
|
||||
<el-input v-model.trim="diyStore.editComponent.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template #label>
|
||||
<div class="flex items-center">
|
||||
<span class="mr-[3px]">{{ t('defaultValue') }}</span>
|
||||
<el-tooltip effect="light" :content="t('defaultValueTips')" placement="top">
|
||||
<el-icon>
|
||||
<QuestionFilled color="#999999" />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<el-input v-model.trim="diyStore.editComponent.field.default"
|
||||
:placeholder="t('defaultValuePlaceholder')" clearable maxlength="18" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('rowCount')">
|
||||
<el-input v-model.trim="diyStore.editComponent.rowCount" :placeholder="t('rowCountPlaceholder')" clearable maxlength="2" show-word-limit />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 表单组件 其他设置 -->
|
||||
<slot name="other"></slot>
|
||||
<!--<el-form label-width="100px" class="px-[10px]">
|
||||
<el-form-item class="display-block">
|
||||
<template #label>
|
||||
<div class="flex items-center">
|
||||
<span class="mr-[3px]">{{ t('隐私保护') }}</span>
|
||||
<el-tooltip effect="light" placement="top">
|
||||
<template #content>
|
||||
<p>会自动将提交的个人信息做加密展示。</p>
|
||||
<p>适用于公开展示收集的数据且不暴露用户隐私。</p>
|
||||
</template>
|
||||
<el-icon>
|
||||
<QuestionFilled color="#999999" />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<el-switch v-model="diyStore.editComponent.field.privacyProtection" />
|
||||
<div class="text-sm text-gray-400">{{ t('提交后自动隐藏文本,仅管理员可查看') }}</div>
|
||||
</el-form-item>
|
||||
</el-form>-->
|
||||
<!-- 表单组件 其他设置 -->
|
||||
<slot name="other"></slot>
|
||||
<!--<el-form label-width="100px" class="px-[10px]">
|
||||
<el-form-item class="display-block">
|
||||
<template #label>
|
||||
<div class="flex items-center">
|
||||
<span class="mr-[3px]">{{ t('隐私保护') }}</span>
|
||||
<el-tooltip effect="light" placement="top">
|
||||
<template #content>
|
||||
<p>会自动将提交的个人信息做加密展示。</p>
|
||||
<p>适用于公开展示收集的数据且不暴露用户隐私。</p>
|
||||
</template>
|
||||
<el-icon>
|
||||
<QuestionFilled color="#999999" />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<el-switch v-model="diyStore.editComponent.field.privacyProtection" />
|
||||
<div class="text-sm text-gray-400">{{ t('提交后自动隐藏文本,仅管理员可查看') }}</div>
|
||||
</el-form-item>
|
||||
</el-form>-->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
|
||||
<!-- 表单组件 字段样式 -->
|
||||
<slot name="style-field"></slot>
|
||||
<!-- 表单组件 字段样式 -->
|
||||
<slot name="style-field"></slot>
|
||||
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
@ -74,7 +75,7 @@ diyStore.editComponent.ignore = ['componentBgUrl'] // 忽略公共属性
|
||||
// 组件验证
|
||||
diyStore.editComponent.verify = (index: number) => {
|
||||
const res = { code: true, message: '' }
|
||||
// todo 只需要考虑该组件自身的验证
|
||||
// todo 只需要考虑该组件自身的验证
|
||||
return res
|
||||
}
|
||||
defineExpose({})
|
||||
|
||||
@ -1,86 +1,88 @@
|
||||
<template>
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
|
||||
<!-- 表单组件 字段内容设置 -->
|
||||
<slot name="field"></slot>
|
||||
<!-- 表单组件 字段内容设置 -->
|
||||
<slot name="field"></slot>
|
||||
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('startTime') }}</h3>
|
||||
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
|
||||
<el-form-item :label="t('formPlaceholder')">
|
||||
<el-input v-model.trim="diyStore.editComponent.start.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('defaultValue')">
|
||||
<el-switch v-model="diyStore.editComponent.start.defaultControl"/>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="diyStore.editComponent.start.defaultControl">
|
||||
<el-radio-group v-model="diyStore.editComponent.start.timeWay">
|
||||
<el-radio label="current">{{ t('currentTime') }}</el-radio>
|
||||
<el-radio label="diy">{{ t('diyTime') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="diyStore.editComponent.start.defaultControl && diyStore.editComponent.start.timeWay == 'diy'">
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('startTime') }}</h3>
|
||||
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
|
||||
<el-form-item :label="t('formPlaceholder')">
|
||||
<el-input v-model.trim="diyStore.editComponent.start.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('defaultValue')">
|
||||
<el-switch v-model="diyStore.editComponent.start.defaultControl" />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="diyStore.editComponent.start.defaultControl">
|
||||
<el-radio-group v-model="diyStore.editComponent.start.timeWay">
|
||||
<el-radio label="current">{{ t('currentTime') }}</el-radio>
|
||||
<el-radio label="diy">{{ t('diyTime') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="diyStore.editComponent.start.defaultControl && diyStore.editComponent.start.timeWay == 'diy'">
|
||||
<el-time-picker v-model="diyStore.editComponent.field.default.start.date" :placeholder="t('startTimePlaceholder')" format="HH:mm" value-format="HH:mm" @change="startTimePickerChange" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('endTime') }}</h3>
|
||||
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
|
||||
<el-form-item :label="t('formPlaceholder')">
|
||||
<el-input v-model.trim="diyStore.editComponent.end.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('defaultValue')">
|
||||
<el-switch v-model="diyStore.editComponent.end.defaultControl" />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="diyStore.editComponent.end.defaultControl">
|
||||
<el-radio-group v-model="diyStore.editComponent.end.timeWay">
|
||||
<el-radio label="current">{{ t('currentTime') }}</el-radio>
|
||||
<el-radio label="diy">{{ t('diyTime') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="diyStore.editComponent.end.defaultControl && diyStore.editComponent.end.timeWay == 'diy'">
|
||||
<el-time-picker :disabled-hours="disabledHours" :disabled-minutes="disabledMinutes" v-model="diyStore.editComponent.field.default.end.date" :placeholder="t('endTimePlaceholder')" format="HH:mm" value-format="HH:mm" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('endTime') }}</h3>
|
||||
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
|
||||
<el-form-item :label="t('formPlaceholder')">
|
||||
<el-input v-model.trim="diyStore.editComponent.end.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('defaultValue')">
|
||||
<el-switch v-model="diyStore.editComponent.end.defaultControl" />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="diyStore.editComponent.end.defaultControl">
|
||||
<el-radio-group v-model="diyStore.editComponent.end.timeWay">
|
||||
<el-radio label="current">{{ t('currentTime') }}</el-radio>
|
||||
<el-radio label="diy">{{ t('diyTime') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="diyStore.editComponent.end.defaultControl && diyStore.editComponent.end.timeWay == 'diy'">
|
||||
<el-time-picker :disabled-hours="disabledHours" :disabled-minutes="disabledMinutes" v-model="diyStore.editComponent.field.default.end.date" :placeholder="t('endTimePlaceholder')" format="HH:mm" value-format="HH:mm" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<!-- 表单组件 其他设置 -->
|
||||
<slot name="other"></slot>
|
||||
</div>
|
||||
<!-- 表单组件 其他设置 -->
|
||||
<slot name="other"></slot>
|
||||
</div>
|
||||
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('textStyle') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('textFontSize')">
|
||||
<el-slider v-model="diyStore.editComponent.fontSize" show-input size="small" class="ml-[10px] diy-nav-slider" :min="12" :max="18" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('textFontWeight')">
|
||||
<el-radio-group v-model="diyStore.editComponent.fontWeight">
|
||||
<el-radio :label="'normal'">{{ t('fontWeightNormal') }}</el-radio>
|
||||
<el-radio :label="'bold'">{{ t('fontWeightBold') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('textColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.textColor" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('textStyle') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('textFontSize')">
|
||||
<el-slider v-model="diyStore.editComponent.fontSize" show-input size="small" class="ml-[10px] diy-nav-slider" :min="12" :max="18" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('textFontWeight')">
|
||||
<el-radio-group v-model="diyStore.editComponent.fontWeight">
|
||||
<el-radio :label="'normal'">{{ t('fontWeightNormal') }}</el-radio>
|
||||
<el-radio :label="'bold'">{{ t('fontWeightBold') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('textColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.textColor" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { t } from '@/lang'
|
||||
import { ref,onMounted } from 'vue'
|
||||
import { ref, onMounted } from 'vue'
|
||||
import useDiyStore from '@/stores/modules/diy'
|
||||
|
||||
const diyStore = useDiyStore()
|
||||
@ -96,25 +98,25 @@ diyStore.editComponent.verify = (index: number) => {
|
||||
const hours = String(today.getHours()).padStart(2, '0');
|
||||
const minutes = String(today.getMinutes()).padStart(2, '0');
|
||||
|
||||
if(diyStore.editComponent.start.timeWay == 'current'){
|
||||
starTime = `${hours}:${minutes}`;
|
||||
if (diyStore.editComponent.start.timeWay == 'current') {
|
||||
starTime = `${ hours }:${ minutes }`;
|
||||
}
|
||||
if(diyStore.editComponent.end.timeWay == 'current'){
|
||||
endTime = `${hours}:${minutes}`;
|
||||
if (diyStore.editComponent.end.timeWay == 'current') {
|
||||
endTime = `${ hours }:${ minutes }`;
|
||||
}
|
||||
|
||||
if(diyStore.editComponent.start.defaultControl && starTime == ''){
|
||||
if (diyStore.editComponent.start.defaultControl && starTime == '') {
|
||||
res.code = false
|
||||
res.message = t('startTimeTips')
|
||||
return res
|
||||
}
|
||||
if(diyStore.editComponent.end.defaultControl && endTime == ''){
|
||||
if (diyStore.editComponent.end.defaultControl && endTime == '') {
|
||||
res.code = false
|
||||
res.message = t('endTimeTips')
|
||||
return res
|
||||
}
|
||||
|
||||
if(diyStore.editComponent.start.defaultControl && diyStore.editComponent.end.defaultControl && timeInvertSecond(starTime) > timeInvertSecond(endTime)){
|
||||
if (diyStore.editComponent.start.defaultControl && diyStore.editComponent.end.defaultControl && timeInvertSecond(starTime) > timeInvertSecond(endTime)) {
|
||||
res.code = false
|
||||
res.message = t('startEndTimeTips')
|
||||
return res
|
||||
@ -122,28 +124,26 @@ diyStore.editComponent.verify = (index: number) => {
|
||||
return res
|
||||
}
|
||||
|
||||
|
||||
onMounted(() => {
|
||||
const today = new Date();
|
||||
const hours = String(today.getHours()).padStart(2, '0');
|
||||
const minutes = String(today.getMinutes()).padStart(2, '0');
|
||||
|
||||
if(!diyStore.editComponent.field.default.start.date){
|
||||
diyStore.editComponent.field.default.start.date = `${hours}:${minutes}`;
|
||||
diyStore.editComponent.field.default.start.timestamp = timeInvertSecond(`${hours}:${minutes}`);
|
||||
if (!diyStore.editComponent.field.default.start.date) {
|
||||
diyStore.editComponent.field.default.start.date = `${ hours }:${ minutes }`;
|
||||
diyStore.editComponent.field.default.start.timestamp = timeInvertSecond(`${ hours }:${ minutes }`);
|
||||
}
|
||||
if(!diyStore.editComponent.field.default.end.date){
|
||||
if (!diyStore.editComponent.field.default.end.date) {
|
||||
let endDate = new Date();
|
||||
endDate.setHours(today.getHours(), today.getMinutes() + 10, 0, 0); // 在当前时间基础上加 10 分钟
|
||||
const endHours = String(endDate.getHours()).padStart(2, '0');
|
||||
const endMinutes = String(endDate.getMinutes()).padStart(2, '0');
|
||||
|
||||
diyStore.editComponent.field.default.end.date = `${endHours}:${endMinutes}`;
|
||||
diyStore.editComponent.field.default.end.timestamp = timeInvertSecond(`${endHours}:${endMinutes}`);
|
||||
diyStore.editComponent.field.default.end.date = `${ endHours }:${ endMinutes }`;
|
||||
diyStore.editComponent.field.default.end.timestamp = timeInvertSecond(`${ endHours }:${ endMinutes }`);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// 开始时间选择器
|
||||
const startTimePickerChange = (e) => {
|
||||
diyStore.editComponent.field.default.start.timestamp = timeInvertSecond(e);
|
||||
@ -152,24 +152,24 @@ const startTimePickerChange = (e) => {
|
||||
const date = new Date();
|
||||
date.setHours(parseInt(startTimeArr[0]), parseInt(startTimeArr[1]), 0, 0);
|
||||
date.setMinutes(date.getMinutes() + 10);
|
||||
const updatedEndTime = `${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}`;
|
||||
const updatedEndTime = `${ String(date.getHours()).padStart(2, '0') }:${ String(date.getMinutes()).padStart(2, '0') }`;
|
||||
diyStore.editComponent.field.default.end.date = updatedEndTime;
|
||||
diyStore.editComponent.field.default.end.timestamp = timeInvertSecond(updatedEndTime);
|
||||
}
|
||||
|
||||
// 结束时间选择器
|
||||
const endTimePickerChange = (e)=>{
|
||||
const endTimePickerChange = (e) => {
|
||||
diyStore.editComponent.field.default.end.timestamp = timeInvertSecond(e);
|
||||
}
|
||||
|
||||
const disabledHours = () => {
|
||||
let timeArr = diyStore.editComponent.field.default.start.date.split(":")
|
||||
return makeRange(0,timeArr[0]);
|
||||
return makeRange(0, timeArr[0]);
|
||||
}
|
||||
|
||||
const disabledMinutes = (hour: number) => {
|
||||
let timeArr = diyStore.editComponent.field.default.start.date.split(":")
|
||||
return makeRange(0,timeArr[1]);
|
||||
return makeRange(0, timeArr[1]);
|
||||
}
|
||||
|
||||
const makeRange = (start: number, end: number) => {
|
||||
@ -180,16 +180,16 @@ const makeRange = (start: number, end: number) => {
|
||||
return result
|
||||
}
|
||||
|
||||
const timeInvertSecond = (time:any)=>{
|
||||
const timeInvertSecond = (time: any) => {
|
||||
let arr = time.split(":");
|
||||
let num = 0;
|
||||
if(arr[0]){
|
||||
if (arr[0]) {
|
||||
num += arr[0] * 60 * 60;
|
||||
}
|
||||
if(arr[1]){
|
||||
if (arr[1]) {
|
||||
num += arr[1] * 60;
|
||||
}
|
||||
if(arr[2]){
|
||||
if (arr[2]) {
|
||||
num += arr[2];
|
||||
}
|
||||
return num;
|
||||
|
||||
@ -1,47 +1,47 @@
|
||||
<template>
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
|
||||
<!-- 表单组件 字段内容设置 -->
|
||||
<slot name="field"></slot>
|
||||
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
|
||||
<el-form-item :label="t('formPlaceholder')">
|
||||
<el-input v-model.trim="diyStore.editComponent.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('defaultValue')">
|
||||
<el-switch v-model="diyStore.editComponent.defaultControl" @change="changeDateDefaultControl" />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="diyStore.editComponent.defaultControl">
|
||||
<el-radio-group v-model="diyStore.editComponent.timeWay">
|
||||
<el-radio label="current">{{ t('currentTime') }}</el-radio>
|
||||
<el-radio label="diy">{{ t('diyTime') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="diyStore.editComponent.defaultControl && diyStore.editComponent.timeWay == 'diy'">
|
||||
<!-- 表单组件 字段内容设置 -->
|
||||
<slot name="field"></slot>
|
||||
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
|
||||
<el-form-item :label="t('formPlaceholder')">
|
||||
<el-input v-model.trim="diyStore.editComponent.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('defaultValue')">
|
||||
<el-switch v-model="diyStore.editComponent.defaultControl" @change="changeDateDefaultControl" />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="diyStore.editComponent.defaultControl">
|
||||
<el-radio-group v-model="diyStore.editComponent.timeWay">
|
||||
<el-radio label="current">{{ t('currentTime') }}</el-radio>
|
||||
<el-radio label="diy">{{ t('diyTime') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="diyStore.editComponent.defaultControl && diyStore.editComponent.timeWay == 'diy'">
|
||||
<el-time-picker v-model="diyStore.editComponent.field.default" :placeholder="t('timePlaceholder')" format="HH:mm" value-format="HH:mm" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 表单组件 其他设置 -->
|
||||
<slot name="other"></slot>
|
||||
<!-- 表单组件 其他设置 -->
|
||||
<slot name="other"></slot>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
|
||||
<!-- 表单组件 字段样式 -->
|
||||
<slot name="style-field"></slot>
|
||||
<!-- 表单组件 字段样式 -->
|
||||
<slot name="style-field"></slot>
|
||||
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { t } from '@/lang'
|
||||
import { ref,watch,onMounted } from 'vue'
|
||||
import { ref, watch, onMounted } from 'vue'
|
||||
import useDiyStore from '@/stores/modules/diy'
|
||||
|
||||
const diyStore = useDiyStore()
|
||||
@ -54,32 +54,32 @@ diyStore.editComponent.verify = (index: number) => {
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// 初始赋值当天时间
|
||||
if (!diyStore.editComponent.field.default) {
|
||||
const today = new Date();
|
||||
const hours = String(today.getHours()).padStart(2, '0');
|
||||
const minutes = String(today.getMinutes()).padStart(2, '0');
|
||||
diyStore.editComponent.field.default = `${hours}:${minutes}`;
|
||||
}
|
||||
});
|
||||
|
||||
const changeDateDefaultControl = (val: any) => {
|
||||
if (val) {
|
||||
const today = new Date();
|
||||
const hours = String(today.getHours()).padStart(2, '0');
|
||||
const minutes = String(today.getMinutes()).padStart(2, '0');
|
||||
diyStore.editComponent.field.default = `${hours}:${minutes}`;
|
||||
}
|
||||
}
|
||||
|
||||
watch(
|
||||
() => diyStore.editComponent.timeWay,
|
||||
(newVal) => {
|
||||
// 初始赋值当天时间
|
||||
if (!diyStore.editComponent.field.default) {
|
||||
const today = new Date();
|
||||
const hours = String(today.getHours()).padStart(2, '0');
|
||||
const minutes = String(today.getMinutes()).padStart(2, '0');
|
||||
diyStore.editComponent.field.default = `${hours}:${minutes}`;
|
||||
}
|
||||
diyStore.editComponent.field.default = `${ hours }:${ minutes }`;
|
||||
}
|
||||
});
|
||||
|
||||
const changeDateDefaultControl = (val: any) => {
|
||||
if (val) {
|
||||
const today = new Date();
|
||||
const hours = String(today.getHours()).padStart(2, '0');
|
||||
const minutes = String(today.getMinutes()).padStart(2, '0');
|
||||
diyStore.editComponent.field.default = `${ hours }:${ minutes }`;
|
||||
}
|
||||
}
|
||||
|
||||
watch(
|
||||
() => diyStore.editComponent.timeWay,
|
||||
(newVal) => {
|
||||
const today = new Date();
|
||||
const hours = String(today.getHours()).padStart(2, '0');
|
||||
const minutes = String(today.getMinutes()).padStart(2, '0');
|
||||
diyStore.editComponent.field.default = `${ hours }:${ minutes }`;
|
||||
}
|
||||
);
|
||||
|
||||
defineExpose({})
|
||||
|
||||
@ -1,30 +1,42 @@
|
||||
<template>
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
|
||||
<!-- 表单组件 字段内容设置 -->
|
||||
<slot name="field"></slot>
|
||||
<el-form label-width="100px" class="px-[10px]">
|
||||
<el-form-item :label="t('上传方式')">
|
||||
<el-radio-group v-model="diyStore.editComponent.uploadMode">
|
||||
<el-radio label="shoot_and_album">{{ t('拍摄和相册') }}</el-radio>
|
||||
<el-radio label="shoot_only">{{ t('只允许拍摄') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<!-- 表单组件 字段内容设置 -->
|
||||
<slot name="field"></slot>
|
||||
<el-form label-width="100px" class="px-[10px]">
|
||||
<el-form-item>
|
||||
<template #label>
|
||||
<div class="flex items-center">
|
||||
<span class="mr-[3px]">{{ t('上传方式') }}</span>
|
||||
<el-tooltip effect="light" :content="t('拍摄时长限制1分钟,从相册上传不限制时长。')" placement="top">
|
||||
<el-icon>
|
||||
<QuestionFilled color="#999999" />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<el-radio-group v-model="diyStore.editComponent.uploadMode">
|
||||
<el-radio label="shoot_and_album">{{ t('拍摄和相册') }}</el-radio>
|
||||
<el-radio label="shoot_only">{{ t('只允许拍摄') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<!-- 表单组件 其他设置 -->
|
||||
<slot name="other"></slot>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
|
||||
<!-- 表单组件 字段样式 -->
|
||||
<slot name="style-field"></slot>
|
||||
<!-- 表单组件 字段样式 -->
|
||||
<slot name="style-field"></slot>
|
||||
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
||||