mirror of
https://gitee.com/niucloud-team/niucloud-admin.git
synced 2026-03-12 19:05:30 +00:00
up admin
This commit is contained in:
parent
c337da9ea3
commit
d98c2dacc1
@ -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 })
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1,12 +1,11 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
|
||||
/**
|
||||
* 登录
|
||||
* @param params
|
||||
*/
|
||||
export function login(params: Record<string, any>) {
|
||||
return request.get(`login`, {params})
|
||||
return request.get(`login`, { params })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -21,15 +20,7 @@ export function logout() {
|
||||
* @returns
|
||||
*/
|
||||
export function getAuthMenus(params: Record<string, any>) {
|
||||
return request.get('auth/authmenu', {params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取登录用户权限
|
||||
* @returns
|
||||
*/
|
||||
export function getSiteInfo() {
|
||||
return request.get('auth/site')
|
||||
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 })
|
||||
}
|
||||
|
||||
@ -727,3 +727,11 @@ export function deleteExport(id: number) {
|
||||
export function getInstallConfig() {
|
||||
return request.get('sys/install/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')
|
||||
}
|
||||
|
||||
/**
|
||||
@ -20,22 +20,22 @@ export function getUpgradeTask() {
|
||||
* 升级
|
||||
* @param addon
|
||||
*/
|
||||
export function upgradeAddon(addon: string = '') {
|
||||
return request.post(addon ? `upgrade/${addon}` : 'upgrade')
|
||||
export function upgradeAddon(addon: string = '', params: Record<string, any> = {}) {
|
||||
return request.post(addon ? `upgrade/${ addon }` : 'upgrade', params)
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行升级
|
||||
*/
|
||||
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,96 @@ 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
|
||||
*/
|
||||
export function delUpgradeRecords(params: Record<string, any>) {
|
||||
return request.delete(`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)
|
||||
}
|
||||
|
||||
@ -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
|
||||
@ -61,11 +62,11 @@ export function getWeappVersionList(params: Record<string, any>) {
|
||||
|
||||
/**
|
||||
* 获取微信小程序上传日志
|
||||
* @param key
|
||||
* @returns
|
||||
* @param key
|
||||
* @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 }`)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -130,4 +131,4 @@ export function deleteVersion(id: string) {
|
||||
*/
|
||||
export function getIsTradeManaged() {
|
||||
return request.get('weapp/delivery/getIsTradeManaged')
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 })
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 80 KiB After Width: | Height: | Size: 74 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) {
|
||||
|
||||
240
admin/src/app/components/upgrade-log/index.vue
Normal file
240
admin/src/app/components/upgrade-log/index.vue
Normal file
@ -0,0 +1,240 @@
|
||||
<template>
|
||||
<el-dialog v-model="dialogVisible" :title="t('gxx')" width="850" :destroy-on-close="true">
|
||||
<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(() => {
|
||||
activeName.value = 0 // 重置
|
||||
|
||||
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,111 +1,214 @@
|
||||
<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">
|
||||
<div class="text-lg">
|
||||
本次升级将从<span class="font-bold">{{ upgradeContent.version }}</span>升级到<span class="font-bold">{{ upgradeContent.upgrade_version }}</span>版本
|
||||
</div>
|
||||
<div class="mt-[10px]" v-if="upgradeContent.upgrade_version != upgradeContent.last_version">
|
||||
<el-alert type="info" show-icon>
|
||||
<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>购买相关服务后再进行升级
|
||||
<template v-if="upgradeContent">
|
||||
<!-- 检测服务是否到期 -->
|
||||
<template v-if="step == 1">
|
||||
<template v-for="(item, index) in upgradeContent.content">
|
||||
<div class="text-lg">
|
||||
<template v-if="item.upgrade_version">
|
||||
<span>【{{ item.app.app_name }}】本次升级将从</span>
|
||||
<span class="font-bold px-[2px]">{{ item.version }}</span>
|
||||
<span>升级到</span>
|
||||
<span class="font-bold px-[2px]">{{ item.upgrade_version }}</span>
|
||||
<span>版本</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<template v-if="upgradeContent.content.length > 1">
|
||||
<span>【{{ item.app.app_name }}】当前版本</span>
|
||||
<span class="font-bold px-[2px]">{{ item.version }}</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span>当前版本</span>
|
||||
<span class="font-bold px-[2px]">{{ item.version }}</span>
|
||||
</template>
|
||||
</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>
|
||||
<div class="mt-[10px]" :class="{ 'mb-[10px]' : (index + 1) < upgradeContent.content.length }" v-if="item.upgrade_version != item.last_version">
|
||||
<el-alert type="info" show-icon :closable="false">
|
||||
<template #title>
|
||||
<span>当前最新版本为{{ item.last_version }},您的服务{{ item.expire_time ? `已于${item.expire_time}到期` : '长期有效' }}。</span>
|
||||
<span>如需升级到最新版可在<a class="text-primary" href="https://www.niucloud.com" target="_blank">niucloud-admin官网</a>购买相关服务后再进行升级</span>
|
||||
</template>
|
||||
</el-alert>
|
||||
</div>
|
||||
</template>
|
||||
</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" v-if="!upgradeContent.last_backup">
|
||||
<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 class="pl-[50px] pt-[50px]" v-else>
|
||||
<el-checkbox v-model="isNeedBackup" :label="t('upgrade.isNeedBackup')" :true-value="true" :false-value="false" size="large" >
|
||||
</el-checkbox>
|
||||
<div class="backup">{{ t('upgrade.isNeedBackupTips') }}<el-button link type="primary" @click="toBackupRecord">{{ t('upgrade.isNeedBackupBtn') }}</el-button></div>
|
||||
</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.content.length && isAllowUpgrade" @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="loading" @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 :loading="readyLoading">{{ 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>
|
||||
@ -116,25 +219,51 @@ 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 {
|
||||
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'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
const router = useRouter()
|
||||
const showDialog = ref<boolean>(false)
|
||||
const upgradeContent = ref<null | AnyObject>(null)
|
||||
const isAllowUpgrade = ref(true) // 是否允许升级
|
||||
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 loading = ref(false)
|
||||
const terminalRef: any = ref(null)
|
||||
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
|
||||
const isNeedBackup = ref(true)
|
||||
|
||||
// 升级步骤排除,backupCode 备份代码,backupSql 备份数据库
|
||||
const excludeSteps: any = ref([
|
||||
{
|
||||
name: '备份源码',
|
||||
code: 'backupCode'
|
||||
},
|
||||
{
|
||||
name: '备份数据库',
|
||||
code: 'backupSql'
|
||||
}
|
||||
])
|
||||
/**
|
||||
* 查询升级任务
|
||||
*/
|
||||
@ -142,6 +271,24 @@ const getUpgradeTaskFn = () => {
|
||||
getUpgradeTask().then(({ data }) => {
|
||||
if (!data) return
|
||||
|
||||
if (!upgradeContent.value) {
|
||||
upgradeContent.value = data.upgrade_content
|
||||
let upgradeCount = 0
|
||||
let failUpgradeCount = 0
|
||||
for (let i = 0; i < upgradeContent.value.content.length; i++) {
|
||||
if (upgradeContent.value.content[i].version_list.length) {
|
||||
upgradeCount++
|
||||
} else {
|
||||
failUpgradeCount++
|
||||
}
|
||||
}
|
||||
if (upgradeContent.value.content.length == upgradeCount) {
|
||||
isAllowUpgrade.value = true
|
||||
} else if (upgradeContent.value.content.length == failUpgradeCount) {
|
||||
isAllowUpgrade.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 检测有没有正在进行中的升级任务
|
||||
if (!showDialog.value) {
|
||||
showElNotification()
|
||||
@ -151,15 +298,18 @@ const getUpgradeTaskFn = () => {
|
||||
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' })
|
||||
errorLog.push(item)
|
||||
@ -168,29 +318,46 @@ const getUpgradeTaskFn = () => {
|
||||
}
|
||||
// 恢复完毕
|
||||
if (data.step == 'restoreComplete') {
|
||||
flashInterval && clearInterval(flashInterval)
|
||||
return
|
||||
}
|
||||
// 升级完成
|
||||
if (data.step == 'upgradeComplete') {
|
||||
active.value = 'complete'
|
||||
numberOfSteps.value = 4
|
||||
notificationEl && notificationEl.close()
|
||||
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
|
||||
/**
|
||||
* 升级中任务提示
|
||||
*/
|
||||
@ -198,10 +365,10 @@ const showElNotification = () => {
|
||||
notificationEl = ElNotification.success({
|
||||
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,16 +376,18 @@ const showElNotification = () => {
|
||||
|
||||
const elNotificationClick = () => {
|
||||
showDialog.value = true
|
||||
active.value = 'upgrade'
|
||||
getUpgradeTaskFn()
|
||||
step.value = 2
|
||||
numberOfSteps.value = 3
|
||||
active.value = 'upgrade'
|
||||
notificationEl && notificationEl.close()
|
||||
}
|
||||
|
||||
const frameworkVersion = ref('')
|
||||
getVersions().then(res => {
|
||||
getVersions().then((res) => {
|
||||
frameworkVersion.value = res.data.version.version
|
||||
})
|
||||
const newFrameworkVersion = ref("")
|
||||
const newFrameworkVersion = ref('')
|
||||
getFrameworkNewVersion().then(({ data }) => {
|
||||
newFrameworkVersion.value = data.last_version
|
||||
})
|
||||
@ -226,44 +395,90 @@ getFrameworkNewVersion().then(({ data }) => {
|
||||
/**
|
||||
* 执行升级
|
||||
*/
|
||||
const is_pass = ref(false)
|
||||
const repeat = ref(false)
|
||||
const readyLoading = ref(false)
|
||||
|
||||
const handleUpgrade = async () => {
|
||||
if (uploading.value) return
|
||||
uploading.value = true
|
||||
if (repeat.value) return
|
||||
repeat.value = true
|
||||
readyLoading.value = true
|
||||
|
||||
const appKey = upgradeContent.value?.app.app_key != 'niucloud-admin' ? upgradeContent.value?.app.app_key : ''
|
||||
const appKey = upgradeContent.value?.upgrade_apps.join(',') != 'niucloud-admin' ? upgradeContent.value?.upgrade_apps.join(',') : ''
|
||||
|
||||
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'
|
||||
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
|
||||
readyLoading.value = false
|
||||
}).catch(() => {
|
||||
repeat.value = false
|
||||
readyLoading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
const open = (addonKey: string = '') => {
|
||||
const upgradeAddonFn = () => {
|
||||
if (!is_pass.value) return
|
||||
if (loading.value) return
|
||||
loading.value = true
|
||||
|
||||
const appKey = upgradeContent.value?.upgrade_apps.join(',') != 'niucloud-admin' ? upgradeContent.value?.upgrade_apps.join(',') : ''
|
||||
|
||||
upgradeAddon(appKey, { is_need_backup: isNeedBackup.value }).then(() => {
|
||||
getUpgradeTaskFn()
|
||||
}).catch(() => {
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
const open = (addonKey: string = '', callback = null) => {
|
||||
if (upgradeTask.value) {
|
||||
ElMessage({ message: '已有正在执行中的升级任务', type: 'error' })
|
||||
showDialog.value = true
|
||||
step.value = 2
|
||||
numberOfSteps.value = 3
|
||||
active.value = 'upgrade'
|
||||
if (callback) callback()
|
||||
} else {
|
||||
if (addonKey && frameworkVersion.value != newFrameworkVersion.value) {
|
||||
ElMessage({ message: '存在新版本框架,请先升级框架', type: 'error' })
|
||||
ElMessage({ message: "存在新版本框架,请先升级框架", type: "error" })
|
||||
if (callback) callback()
|
||||
return
|
||||
}
|
||||
if (loading.value) return
|
||||
loading.value = true
|
||||
getUpgradeContent(addonKey).then(({ data }) => {
|
||||
loading.value = false
|
||||
upgradeContent.value = data
|
||||
let upgradeCount = 0
|
||||
let failUpgradeCount = 0
|
||||
for (let i = 0; i < upgradeContent.value.content.length; i++) {
|
||||
if (upgradeContent.value.content[i].version_list.length) {
|
||||
upgradeCount++
|
||||
} else {
|
||||
failUpgradeCount++
|
||||
}
|
||||
}
|
||||
if (upgradeContent.value.content.length == upgradeCount) {
|
||||
isAllowUpgrade.value = true
|
||||
} else if (upgradeContent.value.content.length == failUpgradeCount) {
|
||||
isAllowUpgrade.value = false
|
||||
}
|
||||
|
||||
if (Storage.get('upgradeTipsLock')) {
|
||||
showDialog.value = true
|
||||
handleUpgrade()
|
||||
} else {
|
||||
upgradeTipsShowDialog.value = true
|
||||
}
|
||||
}).catch()
|
||||
if (callback) callback()
|
||||
}).catch(() => {
|
||||
loading.value = false
|
||||
if (callback) callback()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -283,10 +498,10 @@ const onExecCmd = (key, command, success, failed, name) => {
|
||||
}
|
||||
|
||||
const makeIterator = (array: string[]) => {
|
||||
var nextIndex = 0
|
||||
let nextIndex = 0
|
||||
return {
|
||||
next() {
|
||||
if ((nextIndex + 1) == array.length) {
|
||||
next () {
|
||||
if (nextIndex + 1 == array.length) {
|
||||
nextIndex = 0
|
||||
}
|
||||
return { value: array[nextIndex++] }
|
||||
@ -295,45 +510,71 @@ 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'
|
||||
uploading.value = false
|
||||
active.value = 'upgrade'
|
||||
loading.value = false
|
||||
upgradeTask.value = null
|
||||
upgradeLog = []
|
||||
errorLog = []
|
||||
numberOfSteps.value = 0
|
||||
flashInterval && clearInterval(flashInterval)
|
||||
clearUpgradeTask().then(() => {}).catch()
|
||||
retrySecondInterval && clearInterval(retrySecondInterval)
|
||||
isNeedBackup.value = true
|
||||
step.value = 1
|
||||
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) => {
|
||||
@ -341,9 +582,19 @@ const upgradeTipsConfirm = (isLock: boolean = false) => {
|
||||
upgradeTipsShowDialog.value = false
|
||||
!isLock && (showDialog.value = true)
|
||||
}
|
||||
const activeName = ref(0)
|
||||
const numberOfSteps = ref(0)
|
||||
|
||||
const toBackupRecord = () => {
|
||||
const routeUrl = router.resolve({
|
||||
path: '/tools/backup_records'
|
||||
})
|
||||
window.open(routeUrl.href, '_blank')
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open
|
||||
open,
|
||||
loading
|
||||
})
|
||||
</script>
|
||||
|
||||
@ -351,7 +602,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,25 +0,0 @@
|
||||
{
|
||||
"todayData": "today's data",
|
||||
"memberNumb": "number of member",
|
||||
"numberOfSites": "number of sites",
|
||||
"numberOfVisitors": "number of visitors",
|
||||
"commonlyUsedFunction": "commonly used function",
|
||||
"articleList": "article list",
|
||||
"memberManagement": "member management",
|
||||
"balanceAccount": "balance account",
|
||||
"administrator": "administrator",
|
||||
"WebDecoration": "website decoration",
|
||||
"accessMessage": "access message",
|
||||
"memberDistribution": "membership distribution",
|
||||
"systemInfo": "system environment",
|
||||
"os": "os",
|
||||
"phpVersions": "php version number",
|
||||
"productionEnvironment": "production environment",
|
||||
"versionsInfo": "version information",
|
||||
"versions": "current version",
|
||||
"frame": "framework based",
|
||||
"channel": "access channel",
|
||||
"serviceSupport": "service support",
|
||||
"officialWbsite": "official website",
|
||||
"pageView": "page view"
|
||||
}
|
||||
@ -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": "已经升级到最新版本"
|
||||
}
|
||||
|
||||
18
admin/src/app/lang/zh-cn/app.upgrade.json
Normal file
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,52 +0,0 @@
|
||||
{
|
||||
"dataSummarize": "数据概况",
|
||||
"todayData": "今日数据",
|
||||
"memberNumb": "新增会员数",
|
||||
"orderMoney": "订单金额",
|
||||
"numberOfVisitors": "今日访客数",
|
||||
"commonlyUsedFunction": "常用功能",
|
||||
"articleList": "文章列表",
|
||||
"memberManagement": "会员管理",
|
||||
"balanceAccount": "余额账户",
|
||||
"administrator": "站点用户",
|
||||
"WebDecoration": "网站装修",
|
||||
"accessMessage": "访问消息",
|
||||
"memberDistribution": "会员分布",
|
||||
"systemInfo": "系统环境",
|
||||
"os": "操作系统:",
|
||||
"phpVersions": "PHP版本号:",
|
||||
"productionEnvironment": "生产环境:",
|
||||
"versionsInfo": "版本信息",
|
||||
"versions": "当前版本",
|
||||
"frame": "基于框架",
|
||||
"channel": "获取渠道",
|
||||
"serviceSupport": "官方客服",
|
||||
"officialWbsite": "官网",
|
||||
"pageView": "访问量",
|
||||
"siteInfo":"站点信息",
|
||||
"siteName":"站点名称",
|
||||
"groupName":"站点套餐",
|
||||
"expireTime":"过期时间",
|
||||
"permanent":"永久",
|
||||
"statusName":"站点状态",
|
||||
"newSiteSum": "新增站点数",
|
||||
"total": "总计",
|
||||
"newMemberSum": "新增用户数",
|
||||
"siteList": "站点列表",
|
||||
"sitePackage": "站点套餐",
|
||||
"newSite": "新增站点",
|
||||
"appMarketplace": "应用市场",
|
||||
"siteDistribution": "站点分布",
|
||||
"addUser": "新增用户",
|
||||
"normalSiteSum": "正常站点(个)",
|
||||
"weekExpireSiteCount":"即将到期站点(个)",
|
||||
"expireSiteSum": "过期站点(个)",
|
||||
"noInstallAppSun": "未安装应用(个)",
|
||||
"installAppSun": "已安装应用(个)",
|
||||
"officialAccount": "Niucloud官方公众号",
|
||||
"officialAccountDesc": "微信扫码关注",
|
||||
"WeCom": "客服二维码",
|
||||
"WeComDesc": "扫码联系客服",
|
||||
"tel": "服务热线:",
|
||||
"newVersion": "最新版本"
|
||||
}
|
||||
@ -1,67 +0,0 @@
|
||||
{
|
||||
"todayData": "实时概况",
|
||||
"memberNumb": "新增会员数(人)",
|
||||
"orderMoney": "订单金额(元)",
|
||||
"numberOfSites": "站点数量",
|
||||
"numberOfVisitors": "今日访客数(人)",
|
||||
"commonlyUsedFunction": "常用功能",
|
||||
"articleList": "文章列表",
|
||||
"memberManagement": "会员管理",
|
||||
"balanceAccount": "余额账户",
|
||||
"administrator": "管理员",
|
||||
"WebDecoration": "网站装修",
|
||||
"accessMessage": "访问消息",
|
||||
"memberDistribution": "会员分布",
|
||||
"systemInfo": "系统环境",
|
||||
"os": "操作系统",
|
||||
"phpVersions": "PHP版本号",
|
||||
"productionEnvironment": "生产环境",
|
||||
"versionsInfo": "版本信息",
|
||||
"versions": "当前版本",
|
||||
"frame": "基于框架",
|
||||
"channel": "获取渠道",
|
||||
"serviceSupport": "服务支持",
|
||||
"officialWbsite": "官网",
|
||||
"pageView": "访客数(人)",
|
||||
"siteInfo":"站点信息",
|
||||
"siteName":"站点名称",
|
||||
"groupName":"站点套餐",
|
||||
"expireTime":"过期时间",
|
||||
"permanent":"永久",
|
||||
"statusName":"站点状态",
|
||||
"orderNumber": "订单数(笔)",
|
||||
"wechatCode": "公众号二维码",
|
||||
"wechatCodeDesc": "微信扫码关注",
|
||||
"enterpriseWechatCode": "客服二维码",
|
||||
"enterpriseWechatCodeDesc": "扫码联系客服",
|
||||
"tel": "服务热线:",
|
||||
"message": "请联系客服",
|
||||
"messageTitle": "提示",
|
||||
"accumulative":"累计",
|
||||
"officialAccount": "Niucloud官方公众号",
|
||||
"officialAccountDesc": "微信扫码关注",
|
||||
"WeCom": "添加企业微信群",
|
||||
"path": "地址",
|
||||
"menuName": "名称",
|
||||
"menuNamePlaceholder": "模版名称",
|
||||
"menuBgColor": "背景颜色",
|
||||
"menuImg": "选择图标",
|
||||
"menuDesc": "描述",
|
||||
"addShortcutMenu": "添加快捷模版",
|
||||
"appTemplate": "应用模块",
|
||||
"siteType": "站点类型",
|
||||
"periodTime": "有效期",
|
||||
"renew": "续费",
|
||||
"selectModel": "选择模块",
|
||||
"addMenu": "添加模块",
|
||||
"shortcutLink": "模版",
|
||||
"emptyMenu": "暂无快捷模块",
|
||||
"select": "选择",
|
||||
"custom": "自定义",
|
||||
"accessSite": "访问站点",
|
||||
"pathSelect": "选择模块",
|
||||
"bgColorPlaceholder": "请选择背景色",
|
||||
"iconPlaceholder": "请选择图标",
|
||||
"pathPlaceholder": "请选择链接",
|
||||
"descPlaceholder": "输入描述语…"
|
||||
}
|
||||
@ -1,76 +1,79 @@
|
||||
{
|
||||
"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": "删除插件会把插件目录连同文件全部删除,确定要删除吗?",
|
||||
"batchUpgrade": "批量升级"
|
||||
}
|
||||
|
||||
@ -3,7 +3,6 @@
|
||||
"logging": "登录中",
|
||||
"platform": "管理端",
|
||||
"login" : "登录",
|
||||
"siteLogin": "站点登录",
|
||||
"adminLogin": "平台登录",
|
||||
"userPlaceholder": "请输入您的账号",
|
||||
"passwordPlaceholder": "请输入您的密码",
|
||||
|
||||
@ -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,35 @@
|
||||
{
|
||||
"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。"
|
||||
}
|
||||
|
||||
@ -27,6 +27,8 @@
|
||||
"appPublicCertPathTips": "上传appCertPublicKey文件",
|
||||
"alipayPublicCertPathTips": "上传alipayCertPublicKey文件",
|
||||
"alipayRootCertPathTips": "上传alipayRootCert文件",
|
||||
"operationTip": "温馨提示:打款设置用于会员提现转账,发放红包等场景"
|
||||
|
||||
"operationTip": "温馨提示:打款设置用于会员提现转账,发放红包等场景",
|
||||
"transferTips":"注意:应微信方规定,在2025年1月15日前开通商家转账到零钱服务的商户号可正常使用转账功能,之后开通的不支持使用转账到零钱服务",
|
||||
"wechatpayPublicCert": "微信支付公钥",
|
||||
"wechatpayPublicCertId": "微信支付公钥ID"
|
||||
}
|
||||
|
||||
28
admin/src/app/lang/zh-cn/tools.backup_records.json
Normal file
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": "无"
|
||||
}
|
||||
12
admin/src/app/lang/zh-cn/tools.upgrade_records.json
Normal file
12
admin/src/app/lang/zh-cn/tools.upgrade_records.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"id": "编号",
|
||||
"upgradeName": "内容",
|
||||
"prevVersion": "前一版本",
|
||||
"currentVersion": "版本",
|
||||
"upgradeNamePlaceholder": "请输入内容",
|
||||
"completeTime": "升级时间",
|
||||
"status": "状态",
|
||||
"failReason": "失败原因",
|
||||
"batchDelete": "批量删除",
|
||||
"deleteTips": "确定要删除吗?"
|
||||
}
|
||||
@ -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,73 +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" />
|
||||
<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 { getInstallConfig } from '@/app/api/sys'
|
||||
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 installPhpConfig = ref(null)
|
||||
|
||||
getInstallConfig().then(({ data }) => {
|
||||
installPhpConfig.value = data
|
||||
}).catch()
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
@ -159,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)
|
||||
@ -187,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
|
||||
|
||||
@ -221,47 +152,16 @@ const save = async (formEl: FormInstance | undefined) => {
|
||||
}
|
||||
|
||||
const market = () => {
|
||||
window.open(installPhpConfig.value?.website_url)
|
||||
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>
|
||||
|
||||
@ -59,10 +59,6 @@ const appList = ref<Record<string, any>[]>([])
|
||||
|
||||
const loading = ref(true)
|
||||
const getAppList = async () => {
|
||||
// const res = await getSiteAddons()
|
||||
// appList.value = res.data
|
||||
// loading.value = false
|
||||
|
||||
const res = await getShowApp()
|
||||
appList.value = res.data
|
||||
loading.value = false
|
||||
@ -70,7 +66,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
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>
|
||||
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<!--站点菜单-->
|
||||
<!--平台菜单-->
|
||||
<div class="main-container">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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,10 +27,9 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive } from 'vue'
|
||||
import { ref, reactive, computed } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
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()
|
||||
@ -70,37 +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.value || !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>
|
||||
|
||||
@ -2,7 +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>
|
||||
|
||||
|
||||
@ -238,8 +238,8 @@ route.query.title = route.query.title || ''
|
||||
route.query.back = route.query.back || '/admin/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
|
||||
|
||||
@ -34,7 +34,7 @@
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<el-switch v-model="diyStore.editComponent.field.privacyProtection" />
|
||||
<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>
|
||||
@ -55,7 +55,7 @@
|
||||
|
||||
<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()
|
||||
@ -66,6 +66,15 @@ diyStore.editComponent.verify = (index: number) => {
|
||||
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({})
|
||||
|
||||
|
||||
@ -4,7 +4,147 @@
|
||||
|
||||
<!-- 表单组件 字段内容设置 -->
|
||||
<slot name="field"></slot>
|
||||
todo 此处编写表格组件的属性
|
||||
<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>
|
||||
|
||||
</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>
|
||||
|
||||
<!-- 表单组件 其他设置 -->
|
||||
<slot name="other"></slot>
|
||||
@ -25,20 +165,248 @@
|
||||
|
||||
<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 只需要考虑该组件自身的验证
|
||||
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>
|
||||
|
||||
@ -5,13 +5,25 @@
|
||||
<!-- 表单组件 字段内容设置 -->
|
||||
<slot name="field"></slot>
|
||||
<el-form label-width="100px" class="px-[10px]">
|
||||
<el-form-item :label="t('上传方式')">
|
||||
<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>
|
||||
|
||||
|
||||
@ -50,7 +50,7 @@
|
||||
</el-table-column>
|
||||
<el-table-column prop="update_time" :label="t('updateTime')" min-width="120" />
|
||||
|
||||
<el-table-column :label="t('operation')" fixed="right" align="right" min-width="100">
|
||||
<el-table-column :label="t('operation')" fixed="right" align="right" min-width="130">
|
||||
<template #default="{ row }">
|
||||
<div class="flex items-center justify-end">
|
||||
<el-button type="primary" v-if="row.status == 1 && row.type=='DIY_FORM'" link @click="spreadEvent(row)">{{ t('promotion') }}</el-button>
|
||||
@ -156,7 +156,7 @@
|
||||
</el-dialog>
|
||||
|
||||
<!-- 推广弹出框 -->
|
||||
<form-spread-popup ref="formSpreadPopupRef" />
|
||||
<spread-popup ref="spreadPopupRef" />
|
||||
|
||||
<!-- 表单提交成功页弹出框 -->
|
||||
<form-submit-popup ref="formSubmitPopupRef" @complete="loadDiyFormList" />
|
||||
@ -181,9 +181,9 @@ import { useRoute, useRouter } from 'vue-router'
|
||||
import { setTablePageStorage,getTablePageStorage } from "@/utils/common";
|
||||
import { img } from '@/utils/common'
|
||||
import recordsDetail from '@/app/views/diy_form/records.vue'
|
||||
import formSpreadPopup from '@/app/views/diy_form/components/form-spread-popup.vue'
|
||||
import formSubmitPopup from '@/app/views/diy_form/components/form-submit-popup.vue'
|
||||
import formWritePopup from '@/app/views/diy_form/components/form-write-popup.vue'
|
||||
import spreadPopup from '@/components/spread-popup/index.vue'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
@ -506,12 +506,19 @@ const shareEvent = async (formEl: FormInstance | undefined) => {
|
||||
}
|
||||
|
||||
// 表单推广
|
||||
const formSpreadPopupRef: any = ref(null)
|
||||
const spreadPopupRef = ref(null)
|
||||
|
||||
const spreadEvent = (data: any) => {
|
||||
formSpreadPopupRef.value.show(data)
|
||||
const pagePath = "/app/pages/index/diy_form"
|
||||
const columnName = "form_id"
|
||||
const columnValue = data.form_id
|
||||
const title = "表单推广"
|
||||
const folder = "diy_form"
|
||||
|
||||
spreadPopupRef.value?.show(pagePath, columnName, columnValue, title,folder)
|
||||
}
|
||||
|
||||
|
||||
// 表单提交成功页弹出框
|
||||
const formSubmitPopupRef: any = ref(null)
|
||||
|
||||
|
||||
@ -106,7 +106,7 @@
|
||||
</el-table-column>
|
||||
<!-- <el-table-column fixed prop="create_time" :label="t('填表时间')" min-width="120" /> -->
|
||||
<el-table-column fixed prop="create_time" :label="t('fillInFormTotal')" min-width="500">
|
||||
<template #default="{ row }" @click="">
|
||||
<template #default="{ row }">
|
||||
{{ row.write_count }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
@ -155,9 +155,11 @@
|
||||
<div class="flex mb-[10px]" v-for="(item, index) in formDetail" :key="index">
|
||||
<div class="flex justify-end w-[100px]">{{ item.label }}:</div>
|
||||
<div class="flex ml-[20px]">
|
||||
<div v-if="Array.isArray(item.text)" class="mr-[10px]" v-for="(textItem, i) in item.text" :key="i">
|
||||
{{ textItem }}
|
||||
</div>
|
||||
<template v-if="Array.isArray(item.text)">
|
||||
<div class="mr-[10px]" v-for="(textItem, i) in item.text" :key="i">
|
||||
{{ textItem }}
|
||||
</div>
|
||||
</template>
|
||||
<div v-else>{{ item.text }}</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -180,11 +182,10 @@
|
||||
import { reactive, ref, defineAsyncComponent } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { getDiyFormFieldsList, getDiyFormFieldStat, getFormRecords,getFormRecordsInfo,deleteFormRecords,getFormRecordsMember} from '@/app/api/diy_form'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { img } from '@/utils/common'
|
||||
import { ElMessageBox, FormInstance } from 'element-plus'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const showDialog = ref(false)
|
||||
const activeName = ref('detail_data')
|
||||
@ -197,7 +198,7 @@ const handleClose = (done: () => void) => {
|
||||
showDialog.value = false;
|
||||
}
|
||||
|
||||
const formData = reactive({
|
||||
const formData = reactive({
|
||||
page: 1,
|
||||
limit: 6,
|
||||
total: 0,
|
||||
@ -213,22 +214,22 @@ const formData = reactive({
|
||||
const formFieldsList = ref([])
|
||||
|
||||
// 获取万能表单字段列表
|
||||
const getDiyFormFieldsListFn = (form_id:any)=>{
|
||||
const getDiyFormFieldsListFn = (form_id: any) => {
|
||||
getDiyFormFieldsList({
|
||||
form_id,
|
||||
order: 'field_id',
|
||||
sort: 'asc'
|
||||
}).then((res:any)=>{
|
||||
}).then((res: any) => {
|
||||
formFieldsList.value = res.data;
|
||||
})
|
||||
}
|
||||
|
||||
// 获取字段统计列表
|
||||
const formFieldsStat = ref([])
|
||||
const getDiyFormFieldStatFn = (form_id:any)=>{
|
||||
const getDiyFormFieldStatFn = (form_id: any) => {
|
||||
getDiyFormFieldStat({
|
||||
form_id
|
||||
}).then((res:any)=>{
|
||||
}).then((res: any) => {
|
||||
formFieldsStat.value = res.data;
|
||||
})
|
||||
}
|
||||
@ -257,7 +258,6 @@ const deleteEvent = (row: any) => {
|
||||
form_id: row.form_id
|
||||
}).then(() => {
|
||||
initData();
|
||||
}).catch(() => {
|
||||
})
|
||||
})
|
||||
}
|
||||
@ -273,18 +273,18 @@ const resetFormMember = (formEl: FormInstance | undefined) => {
|
||||
getFormRecordsMemberFn()
|
||||
}
|
||||
|
||||
const loadFormRecordsListFn= (page: number = 1)=>{
|
||||
const loadFormRecordsListFn= (page: number = 1)=> {
|
||||
formData.loading = true
|
||||
formData.page = page
|
||||
getFormRecords({
|
||||
page: formData.page,
|
||||
limit: formData.limit,
|
||||
...formData.searchParam
|
||||
}).then((res:any)=>{
|
||||
}).then((res: any) => {
|
||||
formData.loading = false
|
||||
formData.data = res.data.data
|
||||
formData.data.forEach((item:any)=>{
|
||||
for (let key:any in item.recordsFieldList){
|
||||
formData.data.forEach((item: any) => {
|
||||
for (let key: any in item.recordsFieldList) {
|
||||
if (modules[item.recordsFieldList[key].detailComponent]) {
|
||||
item.recordsFieldList[key].detailComponent && (item.recordsFieldList[key].detailComponent = defineAsyncComponent(modules[item.recordsFieldList[key].detailComponent]))
|
||||
}
|
||||
@ -295,7 +295,7 @@ const loadFormRecordsListFn= (page: number = 1)=>{
|
||||
formData.loading = false
|
||||
})
|
||||
}
|
||||
const formMemberList = reactive({
|
||||
const formMemberList = reactive({
|
||||
page: 1,
|
||||
limit: 10,
|
||||
total: 0,
|
||||
@ -303,7 +303,7 @@ const formMemberList = reactive({
|
||||
data: [],
|
||||
searchParam: {
|
||||
keyword: '',
|
||||
form_id: 0,
|
||||
form_id: 0
|
||||
}
|
||||
})
|
||||
|
||||
@ -320,12 +320,12 @@ const getFormRecordsMemberFn = (page: number = 1) => {
|
||||
formMemberList.loading = false;
|
||||
}).catch((error) => {
|
||||
formMemberList.loading = false;
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
//查看会员详情
|
||||
const detailEvent = (member_id:number)=> {
|
||||
let routeData = router.resolve(`/member/detail?id=${member_id}`)
|
||||
const detailEvent = (member_id:number) => {
|
||||
let routeData = router.resolve(`/member/detail?id=${ member_id }`)
|
||||
window.open(routeData.href, ' blank');
|
||||
}
|
||||
|
||||
@ -338,7 +338,7 @@ const setFormData = async (row: any = null) => {
|
||||
initData();
|
||||
}
|
||||
|
||||
const initData = () =>{
|
||||
const initData = () => {
|
||||
getFormRecordsMemberFn();
|
||||
getDiyFormFieldStatFn(formId.value);
|
||||
loadFormRecordsListFn()
|
||||
@ -387,5 +387,4 @@ defineExpose({
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@ -81,18 +81,18 @@
|
||||
|
||||
<div class="mt-[10px]">
|
||||
<el-table :data="orderTableData.data" size="large" class="table-top">
|
||||
<el-table-column :label="t('memberInfo')" min-width="180" />
|
||||
<el-table-column :label="t('cashOutMethod')" align="center" min-width="100" />
|
||||
<el-table-column :label="t('cashOutInfo')" min-width="180" />
|
||||
<el-table-column :label="t('applicationForWithdrawalAmount')" align="center" min-width="120" />
|
||||
<el-table-column :label="t('actualTransferAmount')" align="center" min-width="120" />
|
||||
<el-table-column :label="t('cashOutCommission')" align="center" min-width="110" />
|
||||
<el-table-column :label="t('cashOutStatus')" align="center" min-width="150" />
|
||||
<el-table-column :label="t('memberInfo')" min-width="180" />
|
||||
<el-table-column :label="t('cashOutMethod')" align="center" min-width="100" />
|
||||
<el-table-column :label="t('cashOutInfo')" min-width="180" />
|
||||
<el-table-column :label="t('applicationForWithdrawalAmount')" align="center" min-width="120" />
|
||||
<el-table-column :label="t('actualTransferAmount')" align="center" min-width="120" />
|
||||
<el-table-column :label="t('cashOutCommission')" align="center" min-width="110" />
|
||||
<el-table-column :label="t('cashOutStatus')" align="center" min-width="150" />
|
||||
<el-table-column :label="t('applyTime')" align="center" min-width="160" />
|
||||
<el-table-column :label="t('auditTime')" align="center" min-width="160" />
|
||||
<el-table-column :label="t('transferTime')" align="center" min-width="160" />
|
||||
<el-table-column :label="t('operation')" fixed="right" align="right" min-width="120" />
|
||||
</el-table>
|
||||
<el-table-column :label="t('operation')" fixed="right" align="right" min-width="120" />
|
||||
</el-table>
|
||||
<div class="table-body min-h-[150px]" v-loading="orderTableData.loading">
|
||||
<div v-if="!orderTableData.loading">
|
||||
<template v-if="orderTableData.data.length">
|
||||
@ -126,7 +126,7 @@
|
||||
<span class="w-[70px] flex-shrink-0 text-right">{{t('account') }}:</span>
|
||||
<span>{{ row.transfer_account }}</span>
|
||||
</div>
|
||||
<div class="flex items-center" v-if="row.transfer_payment_code">
|
||||
<div class="flex items-start" v-if="row.transfer_payment_code">
|
||||
<span class="w-[70px] flex-shrink-0 text-right">{{ t('transferCode') }}:</span>
|
||||
<el-image :src="img(row.transfer_payment_code)" :preview-src-list="[img(row.transfer_payment_code)]" :hide-on-click-modal="true" class="w-[50px] h-[50px]"></el-image>
|
||||
</div>
|
||||
@ -189,9 +189,9 @@
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div v-if="item.remark" class="text-[14px] min-h-[30px] leading-[30px] px-3 bg-[#fff0e5] text-[#ff7f5b] mb-[10px] relative remark">
|
||||
<span class="mr-[5px]">{{ t('notes') }}:</span>
|
||||
<span>{{ item.remark }}</span>
|
||||
</div>
|
||||
<span class="mr-[5px]">{{ t('notes') }}:</span>
|
||||
<span>{{ item.remark }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<el-empty v-else :image-size="1" :description="t('emptyData')" />
|
||||
|
||||
@ -52,13 +52,11 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref, computed } from 'vue'
|
||||
import { reactive, ref, computed,defineEmits } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { getPayRefundInfo, getRefundType, getRefundTransfer } from '@/app/api/pay'
|
||||
import { FormInstance, ElMessage } from 'element-plus'
|
||||
import { FormInstance } from 'element-plus'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { img, filterNumber } from '@/utils/common'
|
||||
import useAppStore from '@/stores/modules/app'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
@ -71,7 +69,6 @@ let refundNo = '';
|
||||
const refundList = ref([])
|
||||
const formData: Record<string, any> = ref(null)
|
||||
|
||||
|
||||
const handleClose = (done: () => void) => {
|
||||
showDialog.value = false;
|
||||
}
|
||||
@ -109,6 +106,7 @@ const transferEvent = (data:any) => {
|
||||
transferDialog.value = true
|
||||
transferFormData.refund_no = data.refund_no
|
||||
transferFormData.refund_money = data.money
|
||||
transferFormData.voucher = ''
|
||||
}
|
||||
|
||||
const initialFormData = {
|
||||
@ -127,6 +125,7 @@ const formRules = computed(() => {
|
||||
]
|
||||
}
|
||||
})
|
||||
const emit = defineEmits(['loadPayRefundList'])
|
||||
|
||||
const confirm = async (formEl: FormInstance | undefined) => {
|
||||
if (loading.value || !formEl) return
|
||||
@ -140,6 +139,7 @@ const confirm = async (formEl: FormInstance | undefined) => {
|
||||
transferDialog.value = false
|
||||
refundList.value = []
|
||||
getRefundListInfo(refundNo)
|
||||
emit('loadPayRefundList')
|
||||
}).catch(() => {
|
||||
transferDialog.value = false
|
||||
loading.value = false
|
||||
|
||||
@ -72,8 +72,7 @@
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<el-image-viewer :url-list="previewImageList" v-if="imageViewerShow" @close="imageViewerShow = false" :initial-index="0"
|
||||
:zoom-rate="1" />
|
||||
<el-image-viewer :url-list="previewImageList" v-if="imageViewerShow" @close="imageViewerShow = false" :initial-index="0" :zoom-rate="1" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
@ -136,13 +135,13 @@ loadPayList()
|
||||
|
||||
const passEvent = (row: AnyObject) => {
|
||||
ElMessageBox.confirm(
|
||||
t('passTips'),
|
||||
t('warning'),
|
||||
{
|
||||
confirmButtonText: t('confirm'),
|
||||
cancelButtonText: t('cancel'),
|
||||
type: 'warning'
|
||||
}
|
||||
t('passTips'),
|
||||
t('warning'),
|
||||
{
|
||||
confirmButtonText: t('confirm'),
|
||||
cancelButtonText: t('cancel'),
|
||||
type: 'warning'
|
||||
}
|
||||
).then(({ value }) => {
|
||||
payAuditPass(row.out_trade_no).then(() => {
|
||||
loadPayList()
|
||||
|
||||
@ -56,14 +56,13 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { getPayDetail, payAuditPass, payAuditRefuse } from '@/app/api/sys'
|
||||
import { img } from '@/utils/common'
|
||||
import { ElMessageBox } from 'element-plus'
|
||||
import { ArrowLeft } from '@element-plus/icons-vue'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const pageName = route.meta.title
|
||||
const id: number = parseInt((route.query.id || 0))
|
||||
const loading = ref(true)
|
||||
@ -81,13 +80,13 @@ setFormData()
|
||||
|
||||
const passEvent = () => {
|
||||
ElMessageBox.confirm(
|
||||
t('passTips'),
|
||||
t('warning'),
|
||||
{
|
||||
confirmButtonText: t('confirm'),
|
||||
cancelButtonText: t('cancel'),
|
||||
type: 'warning'
|
||||
}
|
||||
t('passTips'),
|
||||
t('warning'),
|
||||
{
|
||||
confirmButtonText: t('confirm'),
|
||||
cancelButtonText: t('cancel'),
|
||||
type: 'warning'
|
||||
}
|
||||
).then(({ value }) => {
|
||||
payAuditPass(formData.value.out_trade_no).then(() => {
|
||||
setFormData()
|
||||
|
||||
@ -10,7 +10,14 @@
|
||||
<el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never">
|
||||
<el-form :inline="true" :model="payRefundTable.searchParam" ref="searchFormRef">
|
||||
<el-form-item :label="t('refundNo')" prop="refund_no">
|
||||
<el-input v-model.trim="payRefundTable.searchParam.refund_no" :placeholder="t('refundNoPlaceholder')" />
|
||||
<el-input v-model.trim="payRefundTable.searchParam.refund_no"
|
||||
:placeholder="t('refundNoPlaceholder')" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('status')" prop="status">
|
||||
<el-select v-model="payRefundTable.searchParam.status" clearable class="input-width">
|
||||
<el-option :label="t('selectPlaceholder')" value="" />
|
||||
<el-option :label="item" :value="key" v-for="(item, key) in refundStatusList" :key="key" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('createTime')" prop="create_time">
|
||||
<el-date-picker v-model="payRefundTable.searchParam.create_time" type="datetimerange"
|
||||
@ -36,9 +43,9 @@
|
||||
<el-table-column prop="status_name" :label="t('status')" min-width="120" />
|
||||
<el-table-column prop="create_time" :label="t('createTime')" min-width="160" />
|
||||
<el-table-column :label="t('operation')" fixed="right" align="right" min-width="120">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" link @click="infoEvent(row)">{{ t('info') }}</el-button>
|
||||
</template>
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" link @click="infoEvent(row)">{{ t('info') }}</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
@ -49,22 +56,25 @@
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
<refund-detail ref="refundDetailDialog"></refund-detail>
|
||||
<refund-detail @loadPayRefundList="handleMessage" ref="refundDetailDialog"></refund-detail>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { getPayRefundPages } from '@/app/api/pay'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { getPayRefundPages ,getRefundStatus} from '@/app/api/pay'
|
||||
import { useRoute } from 'vue-router'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import refundDetail from '@/app/views/finance/components/refund-detail.vue'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const pageName = route.meta.title
|
||||
|
||||
const refundStatusList = ref([])
|
||||
const checkStatusList = async () => {
|
||||
refundStatusList.value = await (await getRefundStatus()).data
|
||||
}
|
||||
checkStatusList()
|
||||
const payRefundTable = reactive({
|
||||
page: 1,
|
||||
limit: 10,
|
||||
@ -73,6 +83,7 @@ const payRefundTable = reactive({
|
||||
data: [],
|
||||
searchParam: {
|
||||
refund_no: '',
|
||||
status: '',
|
||||
create_time: []
|
||||
}
|
||||
})
|
||||
@ -99,6 +110,9 @@ const loadPayRefundList = (page: number = 1) => {
|
||||
})
|
||||
}
|
||||
loadPayRefundList()
|
||||
const handleMessage = () => {
|
||||
loadPayRefundList()
|
||||
}
|
||||
const refundDetailDialog: Record<string, any> | null = ref(null)
|
||||
const infoEvent = (res:any) => {
|
||||
let data = {no: res.refund_no};
|
||||
|
||||
@ -36,7 +36,7 @@
|
||||
<div class="px-[20px] pb-[10px] font-bold mt-[40px]">{{ t('weapp') }}</div>
|
||||
<el-form label-width="40px" class="px-[20px]">
|
||||
<el-form-item label=" " v-if="weappConfig.qr_code">
|
||||
<el-image class="w-[100px] h-[100px]" :src="img(weappConfig.qr_code)" />
|
||||
<el-image class="w-[150px] h-[150px]" :src="img(weappConfig.qr_code)" />
|
||||
</el-form-item>
|
||||
<el-form-item label=" " v-else>
|
||||
<span class="text-gray-400">{{ t('weappNotSet') }}</span>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -4,7 +4,7 @@
|
||||
<el-input class="input-width" v-model.trim="formData.continue_sign" @keyup="filterNumber($event)" :maxlength="3" clearable />
|
||||
<span class="ml-[10px]">{{ t('day') }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('continueSign')" >
|
||||
<el-form-item :label="t('continueSignAward')">
|
||||
<div class="flex-1">
|
||||
<div v-for="(item,index) in gifts" :key="index" class="mb-[15px]">
|
||||
<component :is="item.component" v-model="formData[item.key]" ref="giftRefs" v-if="item.component" />
|
||||
@ -38,6 +38,10 @@ const props = defineProps({
|
||||
default: () => {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
sign_period: {
|
||||
type: Number,
|
||||
default: 0
|
||||
}
|
||||
})
|
||||
const emits = defineEmits(['update:modelValue'])
|
||||
@ -94,6 +98,8 @@ const formRules = reactive<FormRules>({
|
||||
callback(t('continueSignFormatError'))
|
||||
} else if (value < 2 || value > 365) {
|
||||
callback(t('continueSignBerweenDays'))
|
||||
} else if (Number(value) > Number(props.sign_period)) {
|
||||
callback(t('continueSignMustLessThanSignPeriod')) // 添加这个校验
|
||||
} else{
|
||||
callback();
|
||||
}
|
||||
@ -126,13 +132,16 @@ const formRules = reactive<FormRules>({
|
||||
|
||||
const verify = async () => {
|
||||
let verify = true
|
||||
await formRef.value?.validate((valid) => {
|
||||
verify = valid
|
||||
})
|
||||
|
||||
if (!verify) return verify
|
||||
|
||||
for (let i = 0; i < giftRefs.value.length; i++) {
|
||||
const item = giftRefs.value[i]
|
||||
!await item.verify() && (verify = false)
|
||||
}
|
||||
await formRef.value?.validate((valid) => {
|
||||
verify = valid
|
||||
})
|
||||
return verify
|
||||
}
|
||||
|
||||
|
||||
@ -40,7 +40,7 @@
|
||||
</span>
|
||||
</div>
|
||||
</el-col>
|
||||
|
||||
|
||||
<template v-for="(item,index) in verifyContentData.fixed">
|
||||
<el-col :span="8">
|
||||
<div class="flex items-center mt-[15px]" v-if="item.title">
|
||||
@ -150,7 +150,6 @@ const getVerifyDetailFn = async () => {
|
||||
}
|
||||
|
||||
const setFormData = async (row: any = null) => {
|
||||
console.log("setFormData",row);
|
||||
code = row.code;
|
||||
getVerifyDetailFn();
|
||||
}
|
||||
|
||||
@ -90,7 +90,7 @@
|
||||
|
||||
<!-- 连签奖励 -->
|
||||
<el-dialog v-model="continueSignDialog" :title="t('continueSignTitle')" width="1200px" :destroy-on-close="true" v-if="formData.is_use">
|
||||
<sign-continue ref="continueRef" v-model="continue_award" />
|
||||
<sign-continue ref="continueRef" v-model="continue_award" :sign_period="formData.sign_period" />
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="continueSignDialog = false">{{ t('cancel') }}</el-button>
|
||||
@ -141,7 +141,21 @@ const regExp: any = {
|
||||
// 表单验证规则
|
||||
const formRules = reactive<FormRules>({
|
||||
day_award: [
|
||||
{ required: true, message: t('daySignAwardPlaceholder'), trigger: 'change' }
|
||||
{
|
||||
required: true,
|
||||
trigger: 'change',
|
||||
validator: (rule: any, value: any, callback: any) => {
|
||||
let isVerify = false
|
||||
daySignAwardText.value.forEach(item => {
|
||||
item.is_use && (isVerify = true)
|
||||
})
|
||||
if (!isVerify) {
|
||||
callback(t('daySignAwardPlaceholder'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
sign_period:[{
|
||||
required: true,
|
||||
|
||||
@ -17,8 +17,8 @@
|
||||
<el-table-column :label="t('memberInfo')" min-width="120">
|
||||
<template #default="{ row }">
|
||||
<div class="flex items-center cursor-pointer " @click="toMember(row.member.member_id)" v-if="row.member">
|
||||
<img class="w-[50px] h-[50px] mr-[10px]" v-if="row.member.headimg" :src="img(row.member.headimg)" alt="">
|
||||
<img class="w-[50px] h-[50px] mr-[10px] rounded-full" v-else src="@/app/assets/images/member_head.png" alt="">
|
||||
<img class="w-[50px] h-[50px] mr-[10px]" v-if="row.member.headimg" :src="img(row.member.headimg)" />
|
||||
<img class="w-[50px] h-[50px] mr-[10px] rounded-full" v-else src="@/app/assets/images/member_head.png" />
|
||||
<div class="flex flex-col">
|
||||
<span>{{ row.member.nickname || '' }}</span>
|
||||
<span>{{ row.member.mobile || '' }}</span>
|
||||
@ -30,17 +30,16 @@
|
||||
<el-table-column :label="t('verifyType')" min-width="120">
|
||||
<template #default="{ row }">
|
||||
<div class="flex flex-col">
|
||||
<div v-for="(item, key) in row.verify_type_array" class="my-[3px]" :key="key">
|
||||
{{ item.verify_type_name }}
|
||||
</div>
|
||||
<div v-for="(item, key) in row.verify_type_array" class="my-[3px]" :key="key">{{ item.verify_type_name }}</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column :label="t('createTime')" prop="create_time" min-width="120" />
|
||||
<el-table-column :label="t('createTime')" prop="create_time" min-width="120"/>
|
||||
|
||||
<el-table-column :label="t('operation')" fixed="right" align="right" width="100">
|
||||
<el-table-column :label="t('operation')" fixed="right" align="right" width="120">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" link @click="editEvent(row)">{{ t('edit') }}</el-button>
|
||||
<el-button type="primary" link @click="deleteEvent(row.id)">{{ t('delete') }}</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@ -48,8 +47,8 @@
|
||||
|
||||
<div class="mt-[16px] flex justify-end">
|
||||
<el-pagination v-model:current-page="verifierTable.page" v-model:page-size="verifierTable.limit"
|
||||
layout="total, sizes, prev, pager, next, jumper" :total="verifierTable.total"
|
||||
@size-change="loadVerifierList()" @current-change="loadVerifierList" />
|
||||
layout="total, sizes, prev, pager, next, jumper" :total="verifierTable.total"
|
||||
@size-change="loadVerifierList()" @current-change="loadVerifierList"/>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
@ -57,13 +56,13 @@
|
||||
<el-dialog v-model="showDialog" :title="t('addVerifier')" width="500px" :destroy-on-close="true">
|
||||
<el-form :model="formData" label-width="90px" ref="formRef" :rules="formRules" class="page-form" v-loading="addLoading">
|
||||
<el-form-item :label="t('member')" prop="member_id">
|
||||
<el-select v-model="formData.member_id" filterable remote reserve-keyword clearable :placeholder="t('searchPlaceholder')" :remote-method="searchMember" :loading="searchLoading" class="input-width">
|
||||
<el-option v-for="item in memberList" :key="item.member_id" :label="item.nickname" :value="item.member_id" />
|
||||
<el-select v-model="formData.member_id" filterable remote reserve-keyword clearable @focus="handleSelectFocus" :disabled="isEditMode" :placeholder="t('searchPlaceholder')" :remote-method="searchMember" :loading="searchLoading" class="input-width">
|
||||
<el-option v-for="item in memberList" :key="item.member_id" :label="item.nickname" :value="item.member_id"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('verifyType')" prop="verify_type">
|
||||
<el-select v-model="formData.verify_type" multiple collapse-tags clearable :placeholder="t('verifyTypePlaceholder')" class="input-width">
|
||||
<el-option v-for="(item, index) in verifyTypeList" :key="index" :label="item.name" :value="index" />
|
||||
<el-select v-model="formData.verify_type" multiple clearable :placeholder="t('verifyTypePlaceholder')" class="input-width">
|
||||
<el-option v-for="(item, index) in verifyTypeList" :key="index" :label="item.name" :value="index"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
@ -79,10 +78,17 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref } from 'vue'
|
||||
import { reactive, ref, nextTick } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { getVerifierList, deleteVerifier, addVerifier, getVerifyTypeList } from '@/app/api/verify'
|
||||
import {
|
||||
getVerifierList,
|
||||
deleteVerifier,
|
||||
addVerifier,
|
||||
getVerifyTypeList,
|
||||
getVerifyInfo,
|
||||
editVerifier
|
||||
} from '@/app/api/verify'
|
||||
import { getMemberList } from '@/app/api/member'
|
||||
import { ElMessageBox, FormInstance } from 'element-plus'
|
||||
import { img } from '@/utils/common'
|
||||
@ -95,12 +101,15 @@ const showDialog = ref(false)
|
||||
const addLoading = ref(false)
|
||||
const formData: Record<string, any> = reactive({
|
||||
member_id: '',
|
||||
verify_type: '',
|
||||
verify_type: ''
|
||||
})
|
||||
|
||||
const formRules = reactive({
|
||||
member_id: [
|
||||
{ required: true, message: t('memberIdPlaceholder'), trigger: 'blur' }
|
||||
],
|
||||
verify_type: [
|
||||
{ required: true, message: t('verifyTypePlaceholder'), trigger: 'blur' }
|
||||
]
|
||||
})
|
||||
const formRef = ref<FormInstance>()
|
||||
@ -137,10 +146,44 @@ loadVerifierList()
|
||||
/**
|
||||
* 添加核销员表
|
||||
*/
|
||||
const isEditMode = ref(false);
|
||||
const addEvent = () => {
|
||||
isEditMode.value = false
|
||||
formData.member_id = ''
|
||||
formData.id = ''
|
||||
formData.verify_type = ''
|
||||
showDialog.value = true
|
||||
}
|
||||
|
||||
const editEvent = async (row: any) => {
|
||||
isEditMode.value = true
|
||||
formData.member_id = ''
|
||||
formData.verify_type = ''
|
||||
memberList.value = []
|
||||
|
||||
try {
|
||||
const res = await getVerifyInfo(row.id)
|
||||
memberList.value = [{
|
||||
member_id: res.data.member.member_id,
|
||||
nickname: res.data.member.nickname
|
||||
}]
|
||||
|
||||
nextTick(() => {
|
||||
formData.member_id = res.data.member.member_id
|
||||
formData.verify_type = res.data.verify_type
|
||||
formData.id = row.id
|
||||
showDialog.value = true
|
||||
})
|
||||
} catch (error) {
|
||||
}
|
||||
}
|
||||
|
||||
const handleSelectFocus = () => {
|
||||
if (isEditMode.value && formData.member_id && memberList.value.length === 0) {
|
||||
searchMember('')
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除核销员表
|
||||
*/
|
||||
@ -168,8 +211,8 @@ const addVerifiers = async (formEl: FormInstance | undefined) => {
|
||||
await formEl.validate(async (valid) => {
|
||||
if (valid) {
|
||||
addLoading.value = true
|
||||
|
||||
addVerifier(formData).then(res => {
|
||||
const api = formData.id ? editVerifier : addVerifier
|
||||
api(formData).then(res => {
|
||||
addLoading.value = false
|
||||
showDialog.value = false
|
||||
formData.member_id = ''
|
||||
@ -193,7 +236,7 @@ const searchMember = (query: string) => {
|
||||
getMemberList({ keyword: query }).then(res => {
|
||||
memberList.value = res.data.data
|
||||
searchLoading.value = false
|
||||
}).catch()
|
||||
})
|
||||
} else {
|
||||
memberList.value = []
|
||||
searchLoading.value = false
|
||||
@ -207,17 +250,16 @@ const verifyTypeList = ref<any>([])
|
||||
const setVerifyTypeList = () => {
|
||||
getVerifyTypeList().then(res => {
|
||||
verifyTypeList.value = res.data
|
||||
}).catch()
|
||||
})
|
||||
}
|
||||
setVerifyTypeList();
|
||||
setVerifyTypeList()
|
||||
|
||||
/**
|
||||
* 会员详情
|
||||
*/
|
||||
const toMember = (member_id: number) => {
|
||||
router.push(`/member/detail?id=${member_id}`)
|
||||
router.push(`/member/detail?id=${ member_id }`)
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
@ -64,7 +64,7 @@
|
||||
@size-change="loadRecordList()" @current-change="loadRecordList" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<verify-detail ref="verifyDetailDialog" />
|
||||
</el-card>
|
||||
</div>
|
||||
@ -73,14 +73,12 @@
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { FormInstance } from 'element-plus'
|
||||
import { getVerifyRecord, getVerifyTypeList, getVerifierSelect } from '@/app/api/verify'
|
||||
import verifyDetail from '@/app/views/marketing/components/verify-detail.vue'
|
||||
import { img } from '@/utils/common'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const pageName = route.meta.title
|
||||
|
||||
const recordTable = reactive({
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('memberId')" >
|
||||
<el-form-item :label="t('memberId')" >
|
||||
<div class="input-width"> {{ formData.member.member_no }} </div>
|
||||
</el-form-item>
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('memberId')" >
|
||||
<el-form-item :label="t('memberId')" >
|
||||
<div class="input-width"> {{ formData.member.member_no }} </div>
|
||||
</el-form-item>
|
||||
|
||||
|
||||
@ -135,7 +135,7 @@ import { t } from '@/lang'
|
||||
import { img } from '@/utils/common'
|
||||
import { getRegisterChannelType, getMemberList, getMemberLabelAll, editMemberStatus, deleteMember, getMemberLevelAll } from '@/app/api/member'
|
||||
import { ElMessageBox, FormInstance } from 'element-plus'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { useRoute } from 'vue-router'
|
||||
import AddMember from '@/app/views/member/components/add-member.vue'
|
||||
import detailMember from '@/app/views/member/components/detail-member.vue'
|
||||
import EditMember from '@/app/views/member/components/edit-member.vue'
|
||||
@ -205,7 +205,6 @@ const loadMemberList = (page: number = 1) => {
|
||||
}
|
||||
loadMemberList()
|
||||
|
||||
const router = useRouter()
|
||||
const addMemberDialog: Record<string, any> | null = ref(null)
|
||||
const editMemberDialog: Record<string, any> | null = ref(null)
|
||||
const detailMemberDialog: Record<string, any> | null = ref(null)
|
||||
|
||||
@ -33,9 +33,7 @@
|
||||
<el-statistic :value="formData.point">
|
||||
<template #title>
|
||||
<div style="display: inline-flex; align-items: center">
|
||||
<span class="text-[14px]">
|
||||
{{ t('point') }}
|
||||
</span>
|
||||
<span class="text-[14px]">{{ t('point') }}</span>
|
||||
<el-tooltip effect="dark" :content="t('adjust')" placement="top">
|
||||
<el-icon @click="adjustPoint(formData)" class="ml-2 cursor-pointer" :size="12">
|
||||
<EditPen color="#273CE2" />
|
||||
@ -64,9 +62,7 @@
|
||||
<el-statistic :value="formData.balance">
|
||||
<template #title>
|
||||
<div style="display: inline-flex; align-items: center">
|
||||
<span class="text-[14px]">
|
||||
{{ t('balance') }}
|
||||
</span>
|
||||
<span class="text-[14px]">{{ t('balance') }}</span>
|
||||
<el-tooltip effect="dark" :content="t('adjust')" placement="top">
|
||||
<el-icon @click="adjustBalance(formData)" class="ml-2 cursor-pointer" :size="12">
|
||||
<EditPen color="#273CE2" />
|
||||
@ -83,9 +79,7 @@
|
||||
<div class="statistic-footer">
|
||||
<div class="footer-item text-[14px] text-secondary">
|
||||
<span>{{ t('accumulative') }}</span>
|
||||
<span class="red ml-1">
|
||||
{{ formData.balance_get }}
|
||||
</span>
|
||||
<span class="red ml-1">{{ formData.balance_get }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -95,9 +89,7 @@
|
||||
<el-statistic :value="formData.growth">
|
||||
<template #title>
|
||||
<div style="display: inline-flex; align-items: center">
|
||||
<span class="text-[14px]">
|
||||
{{ t('growth') }}
|
||||
</span>
|
||||
<span class="text-[14px]">{{ t('growth') }}</span>
|
||||
<!-- <el-tooltip effect="dark" :content="t('adjust')" placement="top">-->
|
||||
<!-- <el-icon @click="adjustGrowth(formData)" class="ml-2 cursor-pointer" :size="12">-->
|
||||
<!-- <EditPen color="#273CE2" />-->
|
||||
@ -118,9 +110,7 @@
|
||||
<el-statistic :value="formData.money" title="New transactions today">
|
||||
<template #title>
|
||||
<div style="display: inline-flex; align-items: center">
|
||||
<span class="text-[14px]">
|
||||
{{ t("money") }}
|
||||
</span>
|
||||
<span class="text-[14px]">{{ t("money") }}</span>
|
||||
<el-tooltip effect="dark" :content="t('detail')" placement="top">
|
||||
<el-icon @click="infoBalance(formData)" class="ml-2 cursor-pointer" :size="12">
|
||||
<View />
|
||||
@ -132,9 +122,7 @@
|
||||
<div class="statistic-footer">
|
||||
<div class="footer-item text-[14px] text-secondary">
|
||||
<span>{{ t('accumulative') }}</span>
|
||||
<span class="green ml-1">
|
||||
{{ formData.money_get }}
|
||||
</span>
|
||||
<span class="green ml-1">{{ formData.money_get }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -144,9 +132,7 @@
|
||||
<el-statistic :value="formData.commission" title="New transactions today">
|
||||
<template #title>
|
||||
<div style="display: inline-flex; align-items: center ">
|
||||
<span class="text-[14px]">
|
||||
{{ t("commission") }}
|
||||
</span>
|
||||
<span class="text-[14px]">{{ t("commission") }}</span>
|
||||
<el-tooltip effect="dark" :content="t('detail')" placement="top">
|
||||
<el-icon @click="infoCommission(formData)" class="ml-2 cursor-pointer" :size="12">
|
||||
<View />
|
||||
@ -158,9 +144,7 @@
|
||||
<div class="statistic-footer">
|
||||
<div class="footer-item text-[14px] text-secondary">
|
||||
<span>{{ t('accumulative') }}</span>
|
||||
<span class="green ml-1">
|
||||
{{ formData.commission_get }}
|
||||
</span>
|
||||
<span class="green ml-1">{{ formData.commission_get }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -172,22 +156,16 @@
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<div class="flex items-center mt-[15px]">
|
||||
<span class="text-[14px] w-[130px] text-right mr-[20px]">{{ t('urserName') }}</span>
|
||||
<span class="text-[14px] text-[#666666]">
|
||||
{{ formData.username || t('notAvailable') }}
|
||||
</span>
|
||||
<span class="text-[14px] text-[#666666]">{{ formData.username || t('notAvailable') }}</span>
|
||||
</div>
|
||||
<div class="flex items-center mt-[15px]">
|
||||
<span class="text-[14px] w-[130px] text-right mr-[20px]">{{ t('nickname') }}</span>
|
||||
<span class="text-[14px] text-[#666666]">
|
||||
{{ formData.nickname || t('notAvailable') }}
|
||||
</span>
|
||||
<span class="text-[14px] text-[#666666]">{{ formData.nickname || t('notAvailable') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center mt-[15px]">
|
||||
<span class="text-[14px] w-[130px] text-right mr-[20px]">{{ t('mobile') }}</span>
|
||||
<span class="text-[14px] text-[#666666]">
|
||||
{{ formData.mobile || t('notAvailable') }}
|
||||
</span>
|
||||
<span class="text-[14px] text-[#666666]">{{ formData.mobile || t('notAvailable') }}</span>
|
||||
</div>
|
||||
<div class="flex items-center mt-[15px]">
|
||||
<span class="text-[14px] w-[130px] text-right mr-[20px]">{{ t('memberLevel') }}</span>
|
||||
@ -276,12 +254,10 @@ import { img } from '@/utils/common'
|
||||
import PointEdit from '@/app/views/member/components/member-point-edit.vue'
|
||||
import BalanceEdit from '@/app/views/member/components/member-balance-edit.vue'
|
||||
import EditMember from '@/app/views/member/components/edit-member.vue'
|
||||
import useAppStore from '@/stores/modules/app'
|
||||
|
||||
const route = useRoute()
|
||||
const pageName = route.meta.title
|
||||
|
||||
const appStore = useAppStore()
|
||||
const loading = ref(true)
|
||||
|
||||
// 获取会员信息
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<!-- 属性内容 -->
|
||||
<div class="content-wrap">
|
||||
<!-- 属性内容 -->
|
||||
<div class="content-wrap">
|
||||
|
||||
<!-- 组件公共属性 -->
|
||||
<slot name="common"></slot>
|
||||
<!-- 组件公共属性 -->
|
||||
<slot name="common"></slot>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<!-- 属性内容 -->
|
||||
<div class="content-wrap">
|
||||
<!-- 属性内容 -->
|
||||
<div class="content-wrap">
|
||||
|
||||
<!-- 组件公共属性 -->
|
||||
<slot name="common"></slot>
|
||||
<!-- 组件公共属性 -->
|
||||
<slot name="common"></slot>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<!-- 属性内容 -->
|
||||
<div class="content-wrap">
|
||||
<!-- 属性内容 -->
|
||||
<div class="content-wrap">
|
||||
|
||||
<!-- 组件公共属性 -->
|
||||
<slot name="common"></slot>
|
||||
<!-- 组件公共属性 -->
|
||||
<slot name="common"></slot>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
||||
@ -1,22 +1,26 @@
|
||||
<template>
|
||||
<!-- 属性内容 -->
|
||||
<div class="content-wrap">
|
||||
<!-- 属性内容 -->
|
||||
<div class="content-wrap">
|
||||
|
||||
<div class="edit-attr-item-wrap">
|
||||
<div class="mb-[10px] text-sm text-primary">{{ t('needLoginTips') }}</div>
|
||||
</div>
|
||||
<div class="edit-attr-item-wrap">
|
||||
<div class="mb-[10px] text-sm text-primary">{{ t('needLoginTips') }}</div>
|
||||
</div>
|
||||
|
||||
<!-- 组件公共属性 -->
|
||||
<slot name="common"></slot>
|
||||
<!-- 组件公共属性 -->
|
||||
<slot name="common"></slot>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('imgShape')">
|
||||
<div class="flex items-center">
|
||||
<div class="bg-[#DFDFDF] cursor-pointer w-[50px] h-[50px] border-solid border-[1px] border-transparent rounded-[50%]" :class="{'border-[var(--el-color-primary)]': posterStore.editComponent.shape == 'circle'}" @click="imgShapeChangeFn('circle')"></div>
|
||||
<div class="bg-[#DFDFDF] cursor-pointer w-[50px] h-[50px] ml-[25px] border-solid border-[1px] border-transparent" :class="{'border-[var(--el-color-primary)]': posterStore.editComponent.shape == 'normal'}" @click="imgShapeChangeFn('normal')"></div>
|
||||
<div class="bg-[#DFDFDF] cursor-pointer w-[50px] h-[50px] border-solid border-[1px] border-transparent rounded-[50%]"
|
||||
:class="{'border-[var(--el-color-primary)]': posterStore.editComponent.shape == 'circle'}"
|
||||
@click="imgShapeChangeFn('circle')"></div>
|
||||
<div class="bg-[#DFDFDF] cursor-pointer w-[50px] h-[50px] ml-[25px] border-solid border-[1px] border-transparent"
|
||||
:class="{'border-[var(--el-color-primary)]': posterStore.editComponent.shape == 'normal'}"
|
||||
@click="imgShapeChangeFn('normal')"></div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
@ -27,7 +31,7 @@ import usePosterStore from '@/stores/modules/poster'
|
||||
const posterStore = usePosterStore()
|
||||
|
||||
// 图片形状改变
|
||||
const imgShapeChangeFn = (data)=>{
|
||||
const imgShapeChangeFn = (data) => {
|
||||
posterStore.editComponent.shape = data;
|
||||
}
|
||||
|
||||
|
||||
@ -1,21 +1,21 @@
|
||||
<template>
|
||||
<!-- 属性内容 -->
|
||||
<div class="content-wrap">
|
||||
<div class="edit-attr-item-wrap">
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('image')">
|
||||
<upload-image v-model="posterStore.editComponent.value" :limit="1"/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<!-- 属性内容 -->
|
||||
<div class="content-wrap">
|
||||
<div class="edit-attr-item-wrap">
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('image')">
|
||||
<upload-image v-model="posterStore.editComponent.value" :limit="1" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<!-- 组件公共属性 -->
|
||||
<slot name="common"></slot>
|
||||
</div>
|
||||
<!-- 组件公共属性 -->
|
||||
<slot name="common"></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref,watch } from 'vue'
|
||||
import { ref, watch } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { img } from '@/utils/common'
|
||||
import usePosterStore from '@/stores/modules/poster'
|
||||
@ -39,7 +39,7 @@ watch(
|
||||
// 设置图片宽高
|
||||
const image = new Image()
|
||||
image.src = img(posterStore.editComponent.value)
|
||||
image.onload = async () => {
|
||||
image.onload = async() => {
|
||||
posterStore.editComponent.imgWidth = image.width
|
||||
posterStore.editComponent.imgHeight = image.height
|
||||
}
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
<template>
|
||||
<!-- 属性内容 -->
|
||||
<div class="content-wrap">
|
||||
<!-- 属性内容 -->
|
||||
<div class="content-wrap">
|
||||
|
||||
<div class="edit-attr-item-wrap">
|
||||
<div class="mb-[10px] text-sm text-primary">{{ t('needLoginTips') }}</div>
|
||||
</div>
|
||||
<div class="edit-attr-item-wrap">
|
||||
<div class="mb-[10px] text-sm text-primary">{{ t('needLoginTips') }}</div>
|
||||
</div>
|
||||
|
||||
<!-- 组件公共属性 -->
|
||||
<slot name="common"></slot>
|
||||
<!-- 组件公共属性 -->
|
||||
<slot name="common"></slot>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
||||
@ -1,39 +1,39 @@
|
||||
<template>
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap">
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('pageContent') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('posterName')">
|
||||
<el-input v-model.trim="posterStore.name" :placeholder="t('posterNamePlaceholder')" clearable maxlength="12" show-word-limit/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('bgType')">
|
||||
<el-radio-group v-model="posterStore.global.bgType">
|
||||
<el-radio :label="'url'">{{ t('bgUrl') }}</el-radio>
|
||||
<el-radio :label="'color'">{{ t('bgColor') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('bgUrl')" v-show="posterStore.global.bgType == 'url'">
|
||||
<upload-image v-model="posterStore.global.bgUrl" :limit="1"/>
|
||||
<div class="text-sm text-gray-400 mt-[10px]">{{ t('bgUrlTips') }}</div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('bgColor')" v-show="posterStore.global.bgType == 'color'">
|
||||
<el-color-picker v-model="posterStore.editComponent.bgColor" :predefine="posterStore.predefineColors" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('statusLabel')" class="display-block">
|
||||
<el-switch v-model="posterStore.status" :active-value="1" :inactive-value="0"/>
|
||||
<div class="text-sm text-gray-400">{{ t('statusTips') }}</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap">
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('pageContent') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('posterName')">
|
||||
<el-input v-model.trim="posterStore.name" :placeholder="t('posterNamePlaceholder')" clearable maxlength="12" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('bgType')">
|
||||
<el-radio-group v-model="posterStore.global.bgType">
|
||||
<el-radio :label="'url'">{{ t('bgUrl') }}</el-radio>
|
||||
<el-radio :label="'color'">{{ t('bgColor') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('bgUrl')" v-show="posterStore.global.bgType == 'url'">
|
||||
<upload-image v-model="posterStore.global.bgUrl" :limit="1" />
|
||||
<div class="text-sm text-gray-400 mt-[10px]">{{ t('bgUrlTips') }}</div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('bgColor')" v-show="posterStore.global.bgType == 'color'">
|
||||
<el-color-picker v-model="posterStore.editComponent.bgColor" :predefine="posterStore.predefineColors" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('statusLabel')" class="display-block">
|
||||
<el-switch v-model="posterStore.status" :active-value="1" :inactive-value="0" />
|
||||
<div class="text-sm text-gray-400">{{ t('statusTips') }}</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { t } from '@/lang'
|
||||
import { watch, ref } from 'vue'
|
||||
import { ref } from 'vue'
|
||||
import { img } from '@/utils/common'
|
||||
import usePosterStore from '@/stores/modules/poster'
|
||||
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<!-- 属性内容 -->
|
||||
<div class="content-wrap">
|
||||
<!-- 属性内容 -->
|
||||
<div class="content-wrap">
|
||||
|
||||
<!-- 组件公共属性 -->
|
||||
<slot name="common"></slot>
|
||||
<!-- 组件公共属性 -->
|
||||
<slot name="common"></slot>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
||||
@ -1,19 +1,19 @@
|
||||
<template>
|
||||
<!-- 属性内容 -->
|
||||
<div class="content-wrap">
|
||||
<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('textLabel')">
|
||||
<el-input v-model.trim="posterStore.editComponent.value" type="textarea" rows="4" :placeholder="t('textPlaceholder')" clearable maxlength="50" show-word-limit />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<!-- 属性内容 -->
|
||||
<div class="content-wrap">
|
||||
<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('textLabel')">
|
||||
<el-input v-model.trim="posterStore.editComponent.value" type="textarea" rows="4" :placeholder="t('textPlaceholder')" clearable maxlength="50" show-word-limit />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<!-- 组件公共属性 -->
|
||||
<slot name="common"></slot>
|
||||
<!-- 组件公共属性 -->
|
||||
<slot name="common"></slot>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
<template>
|
||||
<div class="overflow-hidden" :style="componentStyle"></div>
|
||||
<div class="overflow-hidden" :style="componentStyle"></div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref,computed } from 'vue'
|
||||
import { ref, computed } from 'vue'
|
||||
|
||||
const prop = defineProps({
|
||||
value: {
|
||||
@ -12,17 +12,17 @@ const prop = defineProps({
|
||||
}
|
||||
})
|
||||
|
||||
const data = computed(()=> {
|
||||
const data = computed(() => {
|
||||
return prop.value;
|
||||
})
|
||||
|
||||
const componentStyle = computed(()=> {
|
||||
const componentStyle = computed(() => {
|
||||
var style = '';
|
||||
style += `background-color: ${prop.value.bgColor};`;
|
||||
style += `width: ${prop.value.width}px;height: ${prop.value.height}px;`;
|
||||
style += `background-color: ${ prop.value.bgColor };`;
|
||||
style += `width: ${ prop.value.width }px;height: ${ prop.value.height }px;`;
|
||||
let box: any = document.getElementById(prop.value.id)
|
||||
if (box) {
|
||||
style += `width:${box.offsetWidth}px;height:${box.offsetHeight}px;`;
|
||||
style += `width:${ box.offsetWidth }px;height:${ box.offsetHeight }px;`;
|
||||
}
|
||||
return style;
|
||||
})
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
<template>
|
||||
<div class="overflow-hidden" :style="componentStyle">{{ data.value }}</div>
|
||||
<div class="overflow-hidden" :style="componentStyle">{{ data.value }}</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref,computed } from 'vue'
|
||||
import { ref, computed } from 'vue'
|
||||
import usePosterStore from '@/stores/modules/poster'
|
||||
|
||||
const posterStore = usePosterStore()
|
||||
@ -15,27 +15,27 @@ const prop = defineProps({
|
||||
}
|
||||
})
|
||||
|
||||
const data = computed(()=> {
|
||||
const data = computed(() => {
|
||||
return prop.value;
|
||||
})
|
||||
|
||||
const componentStyle = computed(()=> {
|
||||
const componentStyle = computed(() => {
|
||||
var style = '';
|
||||
style += `font-size: ${prop.value.fontSize}px;color: ${prop.value.fontColor};line-height: ${prop.value.lineHeight + prop.value.fontSize}px;`;
|
||||
if(prop.value.x == 'left' || prop.value.x == 'center' || prop.value.x == 'right'){
|
||||
style += `text-align: ${prop.value.x};`;
|
||||
style += `font-size: ${ prop.value.fontSize }px;color: ${ prop.value.fontColor };line-height: ${ prop.value.lineHeight + prop.value.fontSize }px;`;
|
||||
if (prop.value.x == 'left' || prop.value.x == 'center' || prop.value.x == 'right') {
|
||||
style += `text-align: ${ prop.value.x };`;
|
||||
}
|
||||
if(prop.value.weight){
|
||||
if (prop.value.weight) {
|
||||
style += `font-weight: bold;`;
|
||||
}
|
||||
if(!prop.value.fontFamily || prop.value.fontFamily == 'static/font/SourceHanSansCN-Regular.ttf'){
|
||||
if (!prop.value.fontFamily || prop.value.fontFamily == 'static/font/SourceHanSansCN-Regular.ttf') {
|
||||
style += `font-family: poster_default_font;`;
|
||||
}
|
||||
let box: any = document.getElementById(prop.value.id)
|
||||
if (box) {
|
||||
style += `width:${box.offsetWidth}px;height:${box.offsetHeight}px;`;
|
||||
}else{
|
||||
style += `width:${prop.value.width}px;height:${prop.value.height}px;`;
|
||||
style += `width:${ box.offsetWidth }px;height:${ box.offsetHeight }px;`;
|
||||
} else {
|
||||
style += `width:${ prop.value.width }px;height:${ prop.value.height }px;`;
|
||||
}
|
||||
return style;
|
||||
})
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
<template>
|
||||
<div class="overflow-hidden" :style="componentStyle">{{ data.value }}</div>
|
||||
<div class="overflow-hidden" :style="componentStyle">{{ data.value }}</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref,computed } from 'vue'
|
||||
import { ref, computed } from 'vue'
|
||||
import usePosterStore from '@/stores/modules/poster'
|
||||
|
||||
const posterStore = usePosterStore()
|
||||
@ -15,27 +15,27 @@ const prop = defineProps({
|
||||
}
|
||||
})
|
||||
|
||||
const data = computed(()=> {
|
||||
const data = computed(() => {
|
||||
return prop.value;
|
||||
})
|
||||
|
||||
const componentStyle = computed(()=> {
|
||||
const componentStyle = computed(() => {
|
||||
var style = '';
|
||||
style += `font-size: ${prop.value.fontSize}px;color: ${prop.value.fontColor};line-height: ${prop.value.lineHeight + prop.value.fontSize}px;`;
|
||||
if(prop.value.x == 'left' || prop.value.x == 'center' || prop.value.x == 'right'){
|
||||
style += `text-align: ${prop.value.x};`;
|
||||
style += `font-size: ${ prop.value.fontSize }px;color: ${ prop.value.fontColor };line-height: ${ prop.value.lineHeight + prop.value.fontSize }px;`;
|
||||
if (prop.value.x == 'left' || prop.value.x == 'center' || prop.value.x == 'right') {
|
||||
style += `text-align: ${ prop.value.x };`;
|
||||
}
|
||||
if(prop.value.weight){
|
||||
if (prop.value.weight) {
|
||||
style += `font-weight: bold;`;
|
||||
}
|
||||
if(!prop.value.fontFamily || prop.value.fontFamily == 'static/font/SourceHanSansCN-Regular.ttf'){
|
||||
if (!prop.value.fontFamily || prop.value.fontFamily == 'static/font/SourceHanSansCN-Regular.ttf') {
|
||||
style += `font-family: poster_default_font;`;
|
||||
}
|
||||
let box: any = document.getElementById(prop.value.id)
|
||||
if (box) {
|
||||
style += `width:${box.offsetWidth}px;height:${box.offsetHeight}px;`;
|
||||
}else{
|
||||
style += `width:${prop.value.width}px;height:${prop.value.height}px;`;
|
||||
style += `width:${ box.offsetWidth }px;height:${ box.offsetHeight }px;`;
|
||||
} else {
|
||||
style += `width:${ prop.value.width }px;height:${ prop.value.height }px;`;
|
||||
}
|
||||
return style;
|
||||
})
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<div class="pointer-events-none max-w-[720px]" :style="componentStyle">
|
||||
<img src="@/app/assets/images/default_headimg_square.jpg" class="w-full h-full" />
|
||||
</div>
|
||||
<div class="pointer-events-none max-w-[720px]" :style="componentStyle">
|
||||
<img src="@/app/assets/images/default_headimg_square.jpg" class="w-full h-full" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref,computed } from 'vue'
|
||||
import { ref, computed } from 'vue'
|
||||
import { img } from '@/utils/common'
|
||||
|
||||
const prop = defineProps({
|
||||
@ -15,14 +15,14 @@ const prop = defineProps({
|
||||
}
|
||||
})
|
||||
|
||||
const data = computed(()=> {
|
||||
const data = computed(() => {
|
||||
return prop.value;
|
||||
})
|
||||
|
||||
const componentStyle = computed(()=> {
|
||||
const componentStyle = computed(() => {
|
||||
var style = '';
|
||||
style += `width: ${prop.value.width}px;`;
|
||||
if(prop.value.shape == 'circle'){
|
||||
style += `width: ${ prop.value.width }px;`;
|
||||
if (prop.value.shape == 'circle') {
|
||||
style += `border-radius: 50%; overflow: hidden;`;
|
||||
}
|
||||
return style;
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
<template>
|
||||
<div class="pointer-events-none max-w-[720px]" :style="componentStyle">
|
||||
<img v-if="data.value" :src="img(data.value)" class="w-full h-full" />
|
||||
<img v-else :src="img('static/resource/images/diy/crack_figure.png')" class="w-full h-full" />
|
||||
</div>
|
||||
<div class="pointer-events-none max-w-[720px]" :style="componentStyle">
|
||||
<img v-if="data.value" :src="img(data.value)" class="w-full h-full" />
|
||||
<img v-else :src="img('static/resource/images/diy/crack_figure.png')" class="w-full h-full" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref,computed } from 'vue'
|
||||
import { ref, computed } from 'vue'
|
||||
import { img } from '@/utils/common'
|
||||
|
||||
const prop = defineProps({
|
||||
@ -16,13 +16,13 @@ const prop = defineProps({
|
||||
}
|
||||
})
|
||||
|
||||
const data = computed(()=> {
|
||||
const data = computed(() => {
|
||||
return prop.value;
|
||||
})
|
||||
|
||||
const componentStyle = computed(()=> {
|
||||
const componentStyle = computed(() => {
|
||||
var style = '';
|
||||
style += `width: ${prop.value.width}px;`;
|
||||
style += `width: ${ prop.value.width }px;`;
|
||||
return style;
|
||||
})
|
||||
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
<template>
|
||||
<div class="overflow-hidden" :style="componentStyle">会员昵称</div>
|
||||
<div class="overflow-hidden" :style="componentStyle">会员昵称</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref,computed } from 'vue'
|
||||
import { ref, computed } from 'vue'
|
||||
import usePosterStore from '@/stores/modules/poster'
|
||||
|
||||
const posterStore = usePosterStore()
|
||||
@ -15,27 +15,27 @@ const prop = defineProps({
|
||||
}
|
||||
})
|
||||
|
||||
const data = computed(()=> {
|
||||
const data = computed(() => {
|
||||
return prop.value;
|
||||
})
|
||||
|
||||
const componentStyle = computed(()=> {
|
||||
const componentStyle = computed(() => {
|
||||
var style = '';
|
||||
style += `font-size: ${prop.value.fontSize}px;color: ${prop.value.fontColor};line-height: ${prop.value.lineHeight + prop.value.fontSize}px;`;
|
||||
if(prop.value.x == 'left' || prop.value.x == 'center' || prop.value.x == 'right'){
|
||||
style += `text-align: ${prop.value.x};`;
|
||||
style += `font-size: ${ prop.value.fontSize }px;color: ${ prop.value.fontColor };line-height: ${ prop.value.lineHeight + prop.value.fontSize }px;`;
|
||||
if (prop.value.x == 'left' || prop.value.x == 'center' || prop.value.x == 'right') {
|
||||
style += `text-align: ${ prop.value.x };`;
|
||||
}
|
||||
if(prop.value.weight){
|
||||
if (prop.value.weight) {
|
||||
style += `font-weight: bold;`;
|
||||
}
|
||||
if(!prop.value.fontFamily || prop.value.fontFamily == 'static/font/SourceHanSansCN-Regular.ttf'){
|
||||
if (!prop.value.fontFamily || prop.value.fontFamily == 'static/font/SourceHanSansCN-Regular.ttf') {
|
||||
style += `font-family: poster_default_font;`;
|
||||
}
|
||||
let box: any = document.getElementById(prop.value.id)
|
||||
if (box) {
|
||||
style += `width:${box.offsetWidth}px;height:${box.offsetHeight}px;`;
|
||||
}else{
|
||||
style += `width:${prop.value.width}px;height:${prop.value.height}px;`;
|
||||
style += `width:${ box.offsetWidth }px;height:${ box.offsetHeight }px;`;
|
||||
} else {
|
||||
style += `width:${ prop.value.width }px;height:${ prop.value.height }px;`;
|
||||
}
|
||||
return style;
|
||||
})
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<div class="pointer-events-none max-w-[720px]" :style="componentStyle">
|
||||
<img :src="img('static/resource/images/diy/qrcode.png')" class="w-full h-full" />
|
||||
</div>
|
||||
<div class="pointer-events-none max-w-[720px]" :style="componentStyle">
|
||||
<img :src="img('static/resource/images/diy/qrcode.png')" class="w-full h-full" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref,computed } from 'vue'
|
||||
import { ref, computed } from 'vue'
|
||||
import { img } from '@/utils/common'
|
||||
|
||||
const prop = defineProps({
|
||||
@ -15,13 +15,13 @@ const prop = defineProps({
|
||||
}
|
||||
})
|
||||
|
||||
const data = computed(()=> {
|
||||
const data = computed(() => {
|
||||
return prop.value;
|
||||
})
|
||||
|
||||
const componentStyle = computed(()=> {
|
||||
const componentStyle = computed(() => {
|
||||
var style = '';
|
||||
style += `width: ${prop.value.width}px;`;
|
||||
style += `width: ${ prop.value.width }px;`;
|
||||
return style;
|
||||
})
|
||||
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
<template>
|
||||
<div class="overflow-hidden" :style="componentStyle">{{ data.value }}</div>
|
||||
<div class="overflow-hidden" :style="componentStyle">{{ data.value }}</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref,computed } from 'vue'
|
||||
import { ref, computed } from 'vue'
|
||||
import usePosterStore from '@/stores/modules/poster'
|
||||
|
||||
const posterStore = usePosterStore()
|
||||
@ -15,27 +15,27 @@ const prop = defineProps({
|
||||
}
|
||||
})
|
||||
|
||||
const data = computed(()=> {
|
||||
const data = computed(() => {
|
||||
return prop.value;
|
||||
})
|
||||
|
||||
const componentStyle = computed(()=> {
|
||||
const componentStyle = computed(() => {
|
||||
var style = '';
|
||||
style += `font-size: ${prop.value.fontSize}px;color: ${prop.value.fontColor};line-height: ${prop.value.lineHeight + prop.value.fontSize}px;`;
|
||||
if(prop.value.x == 'left' || prop.value.x == 'center' || prop.value.x == 'right'){
|
||||
style += `text-align: ${prop.value.x};`;
|
||||
style += `font-size: ${ prop.value.fontSize }px;color: ${ prop.value.fontColor };line-height: ${ prop.value.lineHeight + prop.value.fontSize }px;`;
|
||||
if (prop.value.x == 'left' || prop.value.x == 'center' || prop.value.x == 'right') {
|
||||
style += `text-align: ${ prop.value.x };`;
|
||||
}
|
||||
if(prop.value.weight){
|
||||
if (prop.value.weight) {
|
||||
style += `font-weight: bold;`;
|
||||
}
|
||||
if(!prop.value.fontFamily || prop.value.fontFamily == 'static/font/SourceHanSansCN-Regular.ttf'){
|
||||
if (!prop.value.fontFamily || prop.value.fontFamily == 'static/font/SourceHanSansCN-Regular.ttf') {
|
||||
style += `font-family: poster_default_font;`;
|
||||
}
|
||||
let box: any = document.getElementById(prop.value.id)
|
||||
if (box) {
|
||||
style += `width:${box.offsetWidth}px;height:${box.offsetHeight}px;`;
|
||||
}else{
|
||||
style += `width:${prop.value.width}px;height:${prop.value.height}px;`;
|
||||
style += `width:${ box.offsetWidth }px;height:${ box.offsetHeight }px;`;
|
||||
} else {
|
||||
style += `width:${ prop.value.width }px;height:${ prop.value.height }px;`;
|
||||
}
|
||||
return style;
|
||||
})
|
||||
|
||||
@ -82,8 +82,7 @@
|
||||
:style="previewIframeStyle(item)"
|
||||
:class="{ 'selected' : posterStore.currentIndex == index }"
|
||||
@mousedown="posterStore.mouseDown($event,item.id,index)"
|
||||
@click.stop="posterStore.changeCurrentIndex(index,item)"
|
||||
>
|
||||
@click.stop="posterStore.changeCurrentIndex(index,item)">
|
||||
<component :is="modules['preview-' + item.path]" :value="item"/>
|
||||
<span class="box1" @mousedown.stop="posterStore.resizeMouseDown($event,item, index)"></span>
|
||||
<span class="box2" @mousedown.stop="posterStore.resizeMouseDown($event,item, index)"></span>
|
||||
@ -299,7 +298,6 @@ const previewIframeStyle = (data: any)=>{
|
||||
default:
|
||||
style.left = data.x + 'px'
|
||||
}
|
||||
// console.log(data.x,data.y)
|
||||
return style
|
||||
}
|
||||
|
||||
|
||||
@ -1,363 +1,373 @@
|
||||
<template>
|
||||
<div class="main-container">
|
||||
<div class="main-container">
|
||||
<el-card class="card !border-none mb-[15px]" shadow="never">
|
||||
<el-page-header :content="pageName" :icon="ArrowLeft" @back="back" />
|
||||
</el-card>
|
||||
|
||||
<el-form class="page-form" :model="formData" :rules="formRules" label-width="150px" ref="formRef" v-loading="loading">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<el-form class="page-form" :model="formData" :rules="formRules" label-width="150px" ref="formRef"
|
||||
v-loading="loading">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
|
||||
<h3 class="panel-title !text-sm">{{ t('printerSet') }}</h3>
|
||||
<h3 class="panel-title !text-sm">{{ t('printerSet') }}</h3>
|
||||
|
||||
<el-form-item :label="t('printerName')" prop="printer_name">
|
||||
<el-input v-model.trim="formData.printer_name" clearable :placeholder="t('printerNamePlaceholder')" class="input-width" maxlength="20" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('printerName')" prop="printer_name">
|
||||
<el-input v-model.trim="formData.printer_name" clearable :placeholder="t('printerNamePlaceholder')" class="input-width" maxlength="20" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('brand')" prop="brand">
|
||||
<el-select v-model="formData.brand" :placeholder="t('brandPlaceholder')" clearable>
|
||||
<el-option v-for="(item,key) in brandList" :key="key" :label="item" :value="key" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('brand')" prop="brand">
|
||||
<el-select v-model="formData.brand" :placeholder="t('brandPlaceholder')" clearable>
|
||||
<el-option v-for="(item,key) in brandList" :key="key" :label="item" :value="key" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('printerCode')" prop="printer_code">
|
||||
<div>
|
||||
<el-input v-model.trim="formData.printer_code" clearable :placeholder="t('printerCodePlaceholder')" class="input-width" maxlength="30" />
|
||||
<p class="text-[12px] text-[#b2b2b2]">{{ t('printerCodeTips') }}</p>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('printerCode')" prop="printer_code">
|
||||
<div>
|
||||
<el-input v-model.trim="formData.printer_code" clearable :placeholder="t('printerCodePlaceholder')" class="input-width" maxlength="30" />
|
||||
<p class="text-[12px] text-[#b2b2b2]">{{ t('printerCodeTips') }}</p>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('printerKey')" prop="printer_key">
|
||||
<div>
|
||||
<el-input v-model.trim="formData.printer_key" clearable :placeholder="t('printerKeyPlaceholder')" class="input-width" maxlength="30" />
|
||||
<p class="text-[12px] text-[#b2b2b2]">{{ t('printerKeyTips') }}</p>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('printerKey')" prop="printer_key">
|
||||
<div>
|
||||
<el-input v-model.trim="formData.printer_key" clearable :placeholder="t('printerKeyPlaceholder')" class="input-width" maxlength="30" />
|
||||
<p class="text-[12px] text-[#b2b2b2]">{{ t('printerKeyTips') }}</p>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('openId')" prop="open_id">
|
||||
<div>
|
||||
<el-input v-model.trim="formData.open_id" clearable :placeholder="t('openIdPlaceholder')" class="input-width" maxlength="30" />
|
||||
<p class="text-[12px] text-[#b2b2b2]">{{ t('openIdTips') }}</p>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('openId')" prop="open_id">
|
||||
<div>
|
||||
<el-input v-model.trim="formData.open_id" clearable :placeholder="t('openIdPlaceholder')" class="input-width" maxlength="30" />
|
||||
<p class="text-[12px] text-[#b2b2b2]">{{ t('openIdTips') }}</p>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('apikey')" prop="apikey">
|
||||
<div>
|
||||
<el-input v-model.trim="formData.apikey" clearable :placeholder="t('apikeyPlaceholder')" class="input-width" maxlength="60" />
|
||||
<p class="text-[12px] text-[#b2b2b2]">{{ t('apikeyTips') }}</p>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('apikey')" prop="apikey">
|
||||
<div>
|
||||
<el-input v-model.trim="formData.apikey" clearable :placeholder="t('apikeyPlaceholder')" class="input-width" maxlength="60" />
|
||||
<p class="text-[12px] text-[#b2b2b2]">{{ t('apikeyTips') }}</p>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('printWidth')" prop="print_width">
|
||||
<el-radio-group v-model="formData.print_width">
|
||||
<el-radio label="58mm">58mm</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('printWidth')" prop="print_width">
|
||||
<el-radio-group v-model="formData.print_width">
|
||||
<el-radio label="58mm">58mm</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('status')">
|
||||
<el-switch v-model="formData.status" :active-value="1" :inactive-value="0" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('status')">
|
||||
<el-switch v-model="formData.status" :active-value="1" :inactive-value="0" />
|
||||
</el-form-item>
|
||||
|
||||
</el-card>
|
||||
<el-card v-for="(item,index) in printerType" :key="item.key" class="box-card !border-none" shadow="never">
|
||||
<h3 class="panel-title !text-sm">{{ item.title }}</h3>
|
||||
</el-card>
|
||||
<el-card v-for="(item,index) in printerType" :key="item.key" class="box-card !border-none" shadow="never">
|
||||
<h3 class="panel-title !text-sm">{{ item.title }}</h3>
|
||||
|
||||
<div class="flex mb-[10px] py-[8px] bg-[#F5F7F9] text-[14px]">
|
||||
<div class="px-[12px] w-[200px]">{{ t('printTrigger') }}</div>
|
||||
<div class="px-[12px] w-[100px]">{{ t('status') }}</div>
|
||||
<div class="px-[12px] w-[250px]">{{ t('usePrintTemplate') }}</div>
|
||||
<div class="px-[12px] w-[300px] flex-1" v-for="childItem in item.condition" :key="childItem.key">{{ childItem.title }}</div>
|
||||
<div class="px-[12px] w-[200px]">{{ t('printNum') }}</div>
|
||||
</div>
|
||||
<div class="flex mb-[10px] py-[8px] bg-[#F5F7F9] text-[14px]">
|
||||
<div class="px-[12px] w-[200px]">{{ t('printTrigger') }}</div>
|
||||
<div class="px-[12px] w-[100px]">{{ t('status') }}</div>
|
||||
<div class="px-[12px] w-[250px]">{{ t('usePrintTemplate') }}</div>
|
||||
<div class="px-[12px] w-[300px] flex-1" v-for="childItem in item.condition" :key="childItem.key">{{ childItem.title }}</div>
|
||||
<div class="px-[12px] w-[200px]">{{ t('printNum') }}</div>
|
||||
</div>
|
||||
|
||||
<template v-if="item.trigger">
|
||||
<div class="flex bg-[#f8f8f9] mb-[10px] py-[20px]" v-for="(triggerItem,triggerKey) in item.trigger" :key="triggerKey">
|
||||
<template v-if="formData.value[item.key]['trigger_' + triggerKey]">
|
||||
<div class="font-bold w-[200px] px-[12px]">{{ triggerItem }}</div>
|
||||
<div class="w-[100px] px-[12px]">
|
||||
<el-switch v-model="formData.value[item.key]['trigger_' + triggerKey].status" :active-value="1" :inactive-value="0" />
|
||||
</div>
|
||||
<div class="w-[250px] px-[12px]">
|
||||
<el-select v-model="formData.value[item.key]['trigger_' + triggerKey].template_id" :placeholder="t('请选择小票打印模板')" clearable>
|
||||
<el-option v-for="templateItem in templateList[item.key]" :key="templateItem.template_id" :label="templateItem.template_name" :value="templateItem.template_id" />
|
||||
</el-select>
|
||||
</div>
|
||||
<template v-for="childItem in item.condition">
|
||||
<div class="w-[300px] px-[12px] flex-1" v-if="childItem.type == 'checkbox'">
|
||||
<el-checkbox-group v-model="formData.value[item.key]['trigger_' + triggerKey][childItem.key]">
|
||||
<el-checkbox v-for="(checkboxItem, index) in childItem.list" :label="checkboxItem.value" :key="index">{{ checkboxItem.name }}</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</div>
|
||||
</template>
|
||||
<div class="w-[200px] px-[12px]">
|
||||
<el-select v-model="formData.value[item.key]['trigger_' + triggerKey].print_num">
|
||||
<el-option label="1联" :value="1" />
|
||||
<el-option label="2联" :value="2" />
|
||||
<el-option label="3联" :value="3" />
|
||||
<el-option label="4联" :value="4" />
|
||||
</el-select>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="item.trigger">
|
||||
<div class="flex bg-[#f8f8f9] mb-[10px] py-[20px]" v-for="(triggerItem,triggerKey) in item.trigger" :key="triggerKey">
|
||||
<template v-if="formData.value[item.key]['trigger_' + triggerKey]">
|
||||
<div class="font-bold w-[200px] px-[12px]">{{ triggerItem }}</div>
|
||||
<div class="w-[100px] px-[12px]">
|
||||
<el-switch v-model="formData.value[item.key]['trigger_' + triggerKey].status" :active-value="1" :inactive-value="0" />
|
||||
</div>
|
||||
<div class="w-[250px] px-[12px]">
|
||||
<el-select v-model="formData.value[item.key]['trigger_' + triggerKey].template_id" :placeholder="t('请选择小票打印模板')" clearable>
|
||||
<el-option v-for="templateItem in templateList[item.key]" :key="templateItem.template_id" :label="templateItem.template_name" :value="templateItem.template_id" />
|
||||
</el-select>
|
||||
</div>
|
||||
<template v-for="childItem in item.condition">
|
||||
<div class="w-[300px] px-[12px] flex-1" v-if="childItem.type == 'checkbox'">
|
||||
<el-checkbox-group
|
||||
v-model="formData.value[item.key]['trigger_' + triggerKey][childItem.key]">
|
||||
<el-checkbox v-for="(checkboxItem, index) in childItem.list" :label="checkboxItem.value" :key="index">{{ checkboxItem.name }}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</div>
|
||||
</template>
|
||||
<div class="w-[200px] px-[12px]">
|
||||
<el-select v-model="formData.value[item.key]['trigger_' + triggerKey].print_num">
|
||||
<el-option label="1联" :value="1" />
|
||||
<el-option label="2联" :value="2" />
|
||||
<el-option label="3联" :value="3" />
|
||||
<el-option label="4联" :value="4" />
|
||||
</el-select>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
</el-card>
|
||||
</el-form>
|
||||
</el-card>
|
||||
</el-form>
|
||||
|
||||
<div class="fixed-footer-wrap">
|
||||
<div class="fixed-footer">
|
||||
<el-button type="primary" :loading="repeat" @click="confirm(formRef)">{{ t('save') }}</el-button>
|
||||
<el-button @click="back()">{{ t('cancel') }}</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fixed-footer-wrap">
|
||||
<div class="fixed-footer">
|
||||
<el-button type="primary" :loading="repeat" @click="confirm(formRef)">{{ t('save') }}</el-button>
|
||||
<el-button @click="back()">{{ t('cancel') }}</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, computed } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { FormInstance, ElMessage } from 'element-plus'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { deepClone } from '@/utils/common';
|
||||
import { addPrinter, editPrinter,getPrinterInfo,getPrinterType,getPrinterBrand,getPrinterTemplateList } from '@/app/api/printer'
|
||||
import { ref, reactive, computed } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { FormInstance, ElMessage } from 'element-plus'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { deepClone } from '@/utils/common';
|
||||
import {
|
||||
addPrinter,
|
||||
editPrinter,
|
||||
getPrinterInfo,
|
||||
getPrinterType,
|
||||
getPrinterBrand,
|
||||
getPrinterTemplateList
|
||||
} from '@/app/api/printer'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const repeat = ref(false)
|
||||
const loading = ref(true)
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const repeat = ref(false)
|
||||
const loading = ref(true)
|
||||
|
||||
const pageName = route.meta.title
|
||||
const pageName = route.meta.title
|
||||
|
||||
/**
|
||||
* 表单数据
|
||||
*/
|
||||
const initialFormData:any = {
|
||||
printer_id: route.query.printer_id || 0,
|
||||
brand: '',
|
||||
printer_name: '',
|
||||
printer_code: '',
|
||||
printer_key: '',
|
||||
open_id: '',
|
||||
apikey: '',
|
||||
template_type: [],
|
||||
trigger: [],
|
||||
value: {},
|
||||
print_width: '58mm',
|
||||
status: 1,
|
||||
/**
|
||||
* 表单数据
|
||||
*/
|
||||
const initialFormData: any = {
|
||||
printer_id: route.query.printer_id || 0,
|
||||
brand: '',
|
||||
printer_name: '',
|
||||
printer_code: '',
|
||||
printer_key: '',
|
||||
open_id: '',
|
||||
apikey: '',
|
||||
template_type: [],
|
||||
trigger: [],
|
||||
value: {},
|
||||
print_width: '58mm',
|
||||
status: 1,
|
||||
}
|
||||
|
||||
const formData: Record<string, any> = reactive({ ...initialFormData })
|
||||
|
||||
const formRef = ref<FormInstance>()
|
||||
|
||||
// 表单验证规则
|
||||
const formRules = computed(() => {
|
||||
return {
|
||||
printer_name: [
|
||||
{ required: true, message: t('printerNamePlaceholder'), trigger: 'blur' },
|
||||
],
|
||||
brand: [
|
||||
{ required: true, message: t('brandPlaceholder'), trigger: 'blur' },
|
||||
],
|
||||
printer_code: [
|
||||
{ required: true, message: t('printerCodePlaceholder'), trigger: 'blur' },
|
||||
],
|
||||
printer_key: [
|
||||
{ required: true, message: t('printerKeyPlaceholder'), trigger: 'blur' },
|
||||
],
|
||||
open_id: [
|
||||
{ required: true, message: t('openIdPlaceholder'), trigger: 'blur' },
|
||||
],
|
||||
apikey: [
|
||||
{ required: true, message: t('apikeyPlaceholder'), trigger: 'blur' },
|
||||
]
|
||||
}
|
||||
})
|
||||
|
||||
const formData: Record<string, any> = reactive({ ...initialFormData })
|
||||
const printerType = ref([])
|
||||
|
||||
const formRef = ref<FormInstance>()
|
||||
|
||||
// 表单验证规则
|
||||
const formRules = computed(() => {
|
||||
return {
|
||||
printer_name: [
|
||||
{ required: true, message: t('printerNamePlaceholder'), trigger: 'blur' },
|
||||
],
|
||||
brand: [
|
||||
{ required: true, message: t('brandPlaceholder'), trigger: 'blur' },
|
||||
],
|
||||
printer_code: [
|
||||
{ required: true, message: t('printerCodePlaceholder'), trigger: 'blur' },
|
||||
],
|
||||
printer_key: [
|
||||
{ required: true, message: t('printerKeyPlaceholder'), trigger: 'blur' },
|
||||
],
|
||||
open_id: [
|
||||
{ required: true, message: t('openIdPlaceholder'), trigger: 'blur' },
|
||||
],
|
||||
apikey: [
|
||||
{ required: true, message: t('apikeyPlaceholder'), trigger: 'blur' },
|
||||
]
|
||||
}
|
||||
})
|
||||
|
||||
const printerType = ref([])
|
||||
|
||||
const init = async ()=> {
|
||||
await getPrinterType({}).then((res: any) => {
|
||||
if (res.data) {
|
||||
printerType.value = res.data;
|
||||
|
||||
for (let i = 0; i < printerType.value.length; i++) {
|
||||
let item: any = printerType.value[i];
|
||||
|
||||
formData.value[item.key] = {};
|
||||
|
||||
let extendData: any = {};
|
||||
for (let ci = 0; ci < item.condition.length; ci++) {
|
||||
let condition = item.condition[ci];
|
||||
extendData[condition.key] = [];
|
||||
if (condition.type == 'checkbox') {
|
||||
extendData[condition.key] = []; // 默认全选
|
||||
for (let k = 0; k < condition.list.length; k++) {
|
||||
extendData[condition.key].push(condition.list[k].value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let key in item.trigger) {
|
||||
formData.value[item.key]['trigger_' + key] = {
|
||||
status: 1,
|
||||
template_id: '',
|
||||
print_num: 1,
|
||||
};
|
||||
Object.assign(formData.value[item.key]['trigger_' + key], deepClone(extendData));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (!formData.printer_id) {
|
||||
loading.value = false
|
||||
}
|
||||
})
|
||||
|
||||
if (formData.printer_id) {
|
||||
getPrinterInfo(formData.printer_id).then((res: any) => {
|
||||
let data = res.data;
|
||||
if (data) Object.keys(formData).forEach((key: string) => {
|
||||
if (data[key] != undefined) {
|
||||
if (key == 'value') {
|
||||
for (let ck in formData[key]){
|
||||
Object.assign(formData[key][ck],data[key][ck])
|
||||
}
|
||||
} else {
|
||||
formData[key] = data[key]
|
||||
}
|
||||
}
|
||||
})
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
init()
|
||||
|
||||
const brandList = ref([])
|
||||
getPrinterBrand({}).then((res: any) => {
|
||||
brandList.value = res.data;
|
||||
})
|
||||
|
||||
const templateList:any = ref({}) // 小票打印模板列表
|
||||
getPrinterTemplateList({}).then((res:any)=> {
|
||||
const init = async() => {
|
||||
await getPrinterType({}).then((res: any) => {
|
||||
if (res.data) {
|
||||
let data = res.data;
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
let item = data[i];
|
||||
if (templateList.value[item.template_type] == undefined) {
|
||||
templateList.value[item.template_type] = []
|
||||
printerType.value = res.data;
|
||||
|
||||
for (let i = 0; i < printerType.value.length; i++) {
|
||||
let item: any = printerType.value[i];
|
||||
|
||||
formData.value[item.key] = {};
|
||||
|
||||
let extendData: any = {};
|
||||
for (let ci = 0; ci < item.condition.length; ci++) {
|
||||
let condition = item.condition[ci];
|
||||
extendData[condition.key] = [];
|
||||
if (condition.type == 'checkbox') {
|
||||
extendData[condition.key] = []; // 默认全选
|
||||
for (let k = 0; k < condition.list.length; k++) {
|
||||
extendData[condition.key].push(condition.list[k].value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let key in item.trigger) {
|
||||
formData.value[item.key]['trigger_' + key] = {
|
||||
status: 1,
|
||||
template_id: '',
|
||||
print_num: 1,
|
||||
};
|
||||
Object.assign(formData.value[item.key]['trigger_' + key], deepClone(extendData));
|
||||
}
|
||||
templateList.value[item.template_type].push({
|
||||
template_id: item.template_id,
|
||||
template_name: item.template_name,
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
if (!formData.printer_id) {
|
||||
loading.value = false
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* 确认
|
||||
* @param formEl
|
||||
*/
|
||||
const confirm = async(formEl: FormInstance | undefined) => {
|
||||
if (loading.value || !formEl) return
|
||||
|
||||
if (printerType.value.length == 0) {
|
||||
ElMessage({
|
||||
type: 'warning',
|
||||
message: t('printTypeEmpty')
|
||||
if (formData.printer_id) {
|
||||
getPrinterInfo(formData.printer_id).then((res: any) => {
|
||||
let data = res.data;
|
||||
if (data) Object.keys(formData).forEach((key: string) => {
|
||||
if (data[key] != undefined) {
|
||||
if (key == 'value') {
|
||||
for (let ck in formData[key]) {
|
||||
Object.assign(formData[key][ck], data[key][ck])
|
||||
}
|
||||
} else {
|
||||
formData[key] = data[key]
|
||||
}
|
||||
}
|
||||
})
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
init()
|
||||
|
||||
const brandList = ref([])
|
||||
getPrinterBrand({}).then((res: any) => {
|
||||
brandList.value = res.data;
|
||||
})
|
||||
|
||||
const templateList: any = ref({}) // 小票打印模板列表
|
||||
getPrinterTemplateList({}).then((res: any) => {
|
||||
if (res.data) {
|
||||
let data = res.data;
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
let item = data[i];
|
||||
if (templateList.value[item.template_type] == undefined) {
|
||||
templateList.value[item.template_type] = []
|
||||
}
|
||||
templateList.value[item.template_type].push({
|
||||
template_id: item.template_id,
|
||||
template_name: item.template_name,
|
||||
})
|
||||
return;
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
let save = formData.printer_id ? editPrinter : addPrinter
|
||||
/**
|
||||
* 确认
|
||||
* @param formEl
|
||||
*/
|
||||
const confirm = async(formEl: FormInstance | undefined) => {
|
||||
if (loading.value || !formEl) return
|
||||
|
||||
await formEl.validate(async(valid) => {
|
||||
if (valid) {
|
||||
if (printerType.value.length == 0) {
|
||||
ElMessage({
|
||||
type: 'warning',
|
||||
message: t('printTypeEmpty')
|
||||
})
|
||||
return;
|
||||
}
|
||||
|
||||
let validateFlag = false;
|
||||
let validateMessage = '';
|
||||
let save = formData.printer_id ? editPrinter : addPrinter
|
||||
|
||||
for (let i = 0; i < printerType.value.length; i++) {
|
||||
let item: any = printerType.value[i];
|
||||
await formEl.validate(async(valid) => {
|
||||
if (valid) {
|
||||
|
||||
for (let k = 0; k < Object.keys(item.trigger).length; k++) {
|
||||
let triggerItem = Object.keys(item.trigger)[k];
|
||||
if (formData.value[item.key]['trigger_' + triggerItem].status == 0) {
|
||||
continue;
|
||||
}
|
||||
let validateFlag = false;
|
||||
let validateMessage = '';
|
||||
|
||||
if (!formData.value[item.key]['trigger_' + triggerItem].template_id) {
|
||||
validateFlag = true;
|
||||
validateMessage = `请设置${ item.title }[${ item.trigger[triggerItem] }]的小票打印模板`
|
||||
break;
|
||||
}
|
||||
for (let i = 0; i < printerType.value.length; i++) {
|
||||
let item: any = printerType.value[i];
|
||||
|
||||
let isFail = false;
|
||||
for (let ck = 0; ck < item.condition.length; ck++) {
|
||||
let condition = item.condition[ck];
|
||||
if (condition.type == 'checkbox') {
|
||||
if (formData.value[item.key]['trigger_' + triggerItem][condition.key].length == 0) {
|
||||
validateFlag = true;
|
||||
validateMessage = `请设置${ item.title }[${ item.trigger[triggerItem] }]的${ condition.title }`
|
||||
isFail = true;
|
||||
break;
|
||||
}
|
||||
for (let k = 0; k < Object.keys(item.trigger).length; k++) {
|
||||
let triggerItem = Object.keys(item.trigger)[k];
|
||||
if (formData.value[item.key]['trigger_' + triggerItem].status == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!formData.value[item.key]['trigger_' + triggerItem].template_id) {
|
||||
validateFlag = true;
|
||||
validateMessage = `请设置${ item.title }[${ item.trigger[triggerItem] }]的小票打印模板`
|
||||
break;
|
||||
}
|
||||
|
||||
let isFail = false;
|
||||
for (let ck = 0; ck < item.condition.length; ck++) {
|
||||
let condition = item.condition[ck];
|
||||
if (condition.type == 'checkbox') {
|
||||
if (formData.value[item.key]['trigger_' + triggerItem][condition.key].length == 0) {
|
||||
validateFlag = true;
|
||||
validateMessage = `请设置${ item.title }[${ item.trigger[triggerItem] }]的${ condition.title }`
|
||||
isFail = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 防止重复循环
|
||||
if (isFail) {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 防止重复循环
|
||||
if (validateFlag) {
|
||||
if (isFail) {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 防止重复循环
|
||||
if (validateFlag) {
|
||||
ElMessage({
|
||||
type: 'warning',
|
||||
message: validateMessage
|
||||
})
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
formData.template_type = [];
|
||||
formData.trigger = [];
|
||||
|
||||
for (let key in formData.value) {
|
||||
for (let childKey in formData.value[key]) {
|
||||
formData.trigger.push(key + '_' + childKey);
|
||||
}
|
||||
formData.template_type.push(key)
|
||||
}
|
||||
|
||||
if (repeat.value) return
|
||||
repeat.value = true
|
||||
|
||||
let data = formData
|
||||
|
||||
save(data).then(res => {
|
||||
repeat.value = false
|
||||
if (!formData.printer_id) {
|
||||
router.push('/printer/list')
|
||||
}
|
||||
}).catch(err => {
|
||||
repeat.value = false
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const back = () => {
|
||||
router.push('/printer/list')
|
||||
}
|
||||
if (validateFlag) {
|
||||
ElMessage({
|
||||
type: 'warning',
|
||||
message: validateMessage
|
||||
})
|
||||
return;
|
||||
}
|
||||
|
||||
formData.template_type = [];
|
||||
formData.trigger = [];
|
||||
|
||||
for (let key in formData.value) {
|
||||
for (let childKey in formData.value[key]) {
|
||||
formData.trigger.push(key + '_' + childKey);
|
||||
}
|
||||
formData.template_type.push(key)
|
||||
}
|
||||
|
||||
if (repeat.value) return
|
||||
repeat.value = true
|
||||
|
||||
let data = formData
|
||||
|
||||
save(data).then(res => {
|
||||
repeat.value = false
|
||||
if (!formData.printer_id) {
|
||||
router.push('/printer/list')
|
||||
}
|
||||
}).catch(err => {
|
||||
repeat.value = false
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const back = () => {
|
||||
router.push('/printer/list')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
@ -4,9 +4,7 @@
|
||||
|
||||
<div class="flex justify-between items-center mb-[5px]">
|
||||
<span class="text-lg">{{pageName}}</span>
|
||||
<el-button type="primary" @click="addEvent">
|
||||
{{ t('addPrinter') }}
|
||||
</el-button>
|
||||
<el-button type="primary" @click="addEvent">{{ t('addPrinter') }}</el-button>
|
||||
</div>
|
||||
|
||||
<el-tabs class="demo-tabs" model-value="/printer/list" @tab-change="handleClick">
|
||||
@ -41,8 +39,8 @@
|
||||
|
||||
<el-table-column prop="status" :label="t('status')" min-width="80" :show-overflow-tooltip="true" >
|
||||
<template #default="{ row }">
|
||||
<el-tag type="success" v-if="row.status == 1" @click="modifyPrinterStatusEvent(row.printer_id, 0)" class="cursor-pointer">{{ t('statusOn') }}</el-tag>
|
||||
<el-tag type="info" v-else @click="modifyPrinterStatusEvent(row.printer_id, 1)" class="cursor-pointer">{{ t('statusOff') }}</el-tag>
|
||||
<el-tag type="success" v-if="row.status == 1" @click="modifyPrinterStatusEvent(row.printer_id, 0)" class="cursor-pointer">{{ t('statusOn') }}</el-tag>
|
||||
<el-tag type="info" v-else @click="modifyPrinterStatusEvent(row.printer_id, 1)" class="cursor-pointer">{{ t('statusOff') }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
@ -73,6 +71,7 @@ import { t } from '@/lang'
|
||||
import { getPrinterPageList, modifyPrinterStatus, deletePrinter,refreshPrinterToken,testPrint } from '@/app/api/printer'
|
||||
import { ElMessageBox,FormInstance } from 'element-plus'
|
||||
import { useRoute,useRouter } from 'vue-router'
|
||||
import { setTablePageStorage,getTablePageStorage } from "@/utils/common";
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
@ -89,8 +88,8 @@ const printerTable = reactive({
|
||||
total: 0,
|
||||
loading: true,
|
||||
data: [],
|
||||
searchParam:{
|
||||
printer_name:''
|
||||
searchParam: {
|
||||
printer_name: ''
|
||||
}
|
||||
})
|
||||
|
||||
@ -106,17 +105,18 @@ const loadPrinterList = (page: number = 1) => {
|
||||
getPrinterPageList({
|
||||
page: printerTable.page,
|
||||
limit: printerTable.limit,
|
||||
...printerTable.searchParam
|
||||
...printerTable.searchParam
|
||||
}).then(res => {
|
||||
printerTable.loading = false
|
||||
printerTable.data = res.data.data
|
||||
printerTable.total = res.data.total
|
||||
setTablePageStorage(printerTable.page, printerTable.limit, printerTable.searchParam);
|
||||
}).catch(() => {
|
||||
printerTable.loading = false
|
||||
})
|
||||
}
|
||||
|
||||
loadPrinterList()
|
||||
loadPrinterList(getTablePageStorage(printerTable.searchParam).page)
|
||||
|
||||
const isRepeat = ref(false)
|
||||
|
||||
@ -224,4 +224,4 @@ const refreshTokenEvent = (printer_id: any) => {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@ -1,349 +1,354 @@
|
||||
<template>
|
||||
<div class="main-container">
|
||||
<div class="main-container">
|
||||
<el-card class="card !border-none mb-[15px]" shadow="never">
|
||||
<el-page-header :content="pageName" :icon="ArrowLeft" @back="back" />
|
||||
</el-card>
|
||||
|
||||
<el-form class="page-form" :model="formData" :rules="formRules" label-width="150px" ref="formRef" v-loading="loading">
|
||||
<el-form class="page-form" :model="formData" :rules="formRules" label-width="150px" ref="formRef" v-loading="loading">
|
||||
|
||||
<div class="flex">
|
||||
<div class="flex">
|
||||
|
||||
<div class="flex-1 mr-[20px] bg-[#fff]">
|
||||
<div class="flex-1 mr-[20px] bg-[#fff]">
|
||||
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
|
||||
<h3 class="panel-title !text-sm">{{ t('templateInfoLabel') }}</h3>
|
||||
<h3 class="panel-title !text-sm">{{ t('templateInfoLabel') }}</h3>
|
||||
|
||||
<el-form-item :label="t('templateName')" prop="template_name">
|
||||
<el-input v-model.trim="formData.template_name" clearable :placeholder="t('templateNamePlaceholder')" class="input-width" maxlength="20" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('templateName')" prop="template_name">
|
||||
<el-input v-model.trim="formData.template_name" clearable :placeholder="t('templateNamePlaceholder')" class="input-width" maxlength="20" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('templateType')" prop="template_type" v-if="printerType.length">
|
||||
<el-radio-group v-model="formData.template_type">
|
||||
<el-radio v-for="item in printerType" :key="item.key" :label="item.key" @change="handlePrintType">{{ item.title }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('templateType')" prop="template_type" v-if="printerType.length">
|
||||
<el-radio-group v-model="formData.template_type">
|
||||
<el-radio v-for="item in printerType" :key="item.key" :label="item.key" @change="handlePrintType">{{ item.title }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
</el-card>
|
||||
<el-card class="box-card !border-none" shadow="never" v-if="printerType.length">
|
||||
</el-card>
|
||||
<el-card class="box-card !border-none" shadow="never" v-if="printerType.length">
|
||||
|
||||
<h3 class="panel-title !text-sm">{{ t('templateEditLabel') }}</h3>
|
||||
<h3 class="panel-title !text-sm">{{ t('templateEditLabel') }}</h3>
|
||||
|
||||
<div v-for="item in template" :key="item.key" class="bg-[#f8f8f9] mb-[20px] py-[20px] px-[40px] text-[14px]">
|
||||
<h4 class="panel-title !text-sm">{{ item.title }}</h4>
|
||||
<div v-for="(childItem,index) in item.list" :key="childItem.key" class="ml-[30px]" :style="{ 'margin-bottom' : item.list.length == (index + 1) ? '0' : '20px' }">
|
||||
<div class="flex">
|
||||
<el-checkbox v-model="formData.value[item.key][childItem.key].status" v-if="childItem.label" :label="childItem.label" :value="childItem.status" :true-value="1" :false-value="0" class="w-[180px] mr-[10px]" :disabled="childItem.disabled" />
|
||||
<div v-for="item in template" :key="item.key" class="bg-[#f8f8f9] mb-[20px] py-[20px] px-[40px] text-[14px]">
|
||||
<h4 class="panel-title !text-sm">{{ item.title }}</h4>
|
||||
<div v-for="(childItem,index) in item.list" :key="childItem.key" class="ml-[30px]" :style="{ 'margin-bottom' : item.list.length == (index + 1) ? '0' : '20px' }">
|
||||
<div class="flex">
|
||||
<el-checkbox v-model="formData.value[item.key][childItem.key].status"
|
||||
v-if="childItem.label" :label="childItem.label"
|
||||
:value="childItem.status" :true-value="1" :false-value="0"
|
||||
class="w-[180px] mr-[10px]" :disabled="childItem.disabled" />
|
||||
|
||||
<template v-if="childItem.type == 'input'">
|
||||
<el-input v-model.trim="formData.value[item.key][childItem.key].value" clearable :placeholder="'请输入' + (childItem.placeholder ? childItem.placeholder : childItem.label)" class="input-width mr-[30px]" maxlength="32" />
|
||||
</template>
|
||||
<template v-if="childItem.type == 'input'">
|
||||
<el-input v-model.trim="formData.value[item.key][childItem.key].value" clearable
|
||||
:placeholder="'请输入' + (childItem.placeholder ? childItem.placeholder : childItem.label)"
|
||||
class="input-width mr-[30px]" maxlength="32" />
|
||||
</template>
|
||||
|
||||
<template v-if="childItem.type == 'checkbox'">
|
||||
<el-checkbox-group v-model="formData.value[item.key][childItem.key].value" class="mr-[30px]">
|
||||
<el-checkbox v-for="(checkboxItem, key) in childItem.list" :label="key" :key="key" :disabled="childItem.disabled">{{ checkboxItem }}</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</template>
|
||||
<template v-if="childItem.type == 'checkbox'">
|
||||
<el-checkbox-group v-model="formData.value[item.key][childItem.key].value" class="mr-[30px]">
|
||||
<el-checkbox v-for="(checkboxItem, key) in childItem.list" :label="key" :key="key" :disabled="childItem.disabled">{{ checkboxItem }}</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</template>
|
||||
|
||||
<template v-if="childItem.type == 'select'">
|
||||
<template v-if="childItem.type == 'select'">
|
||||
|
||||
<div class="leading-[30px] w-[50px] text-center text-[#707070] bg-[#d7d7d7] border-1 border-solid border-[#ededed]">{{ childItem.text }}</div>
|
||||
<el-select v-model="formData.value[item.key][childItem.key].value" class="!w-[130px] mr-[30px]">
|
||||
<el-option v-for="(item,key) in childItem.list" :key="key" :label="item" :value="key" />
|
||||
</el-select>
|
||||
<div class="leading-[30px] w-[50px] text-center text-[#707070] bg-[#d7d7d7] border-1 border-solid border-[#ededed]">{{ childItem.text }}</div>
|
||||
<el-select v-model="formData.value[item.key][childItem.key].value" class="!w-[130px] mr-[30px]">
|
||||
<el-option v-for="(item,key) in childItem.list" :key="key" :label="item" :value="key" />
|
||||
</el-select>
|
||||
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<template v-if="childItem.fontSize">
|
||||
<div class="flex mr-[30px]">
|
||||
<div class="leading-[30px] w-[50px] text-center text-[#707070] bg-[#d7d7d7] border-1 border-solid border-[#ededed]">字号</div>
|
||||
<el-select v-model="formData.value[item.key][childItem.key].fontSize" class="!w-[130px]">
|
||||
<el-option label="小" value="normal" />
|
||||
<!-- <el-option label="小" value="small" />-->
|
||||
<el-option label="大" value="big" />
|
||||
</el-select>
|
||||
</div>
|
||||
<template v-if="childItem.fontSize">
|
||||
<div class="flex mr-[30px]">
|
||||
<div class="leading-[30px] w-[50px] text-center text-[#707070] bg-[#d7d7d7] border-1 border-solid border-[#ededed]">字号</div>
|
||||
<el-select v-model="formData.value[item.key][childItem.key].fontSize" class="!w-[130px]">
|
||||
<el-option label="小" value="normal" />
|
||||
<!--<el-option label="小" value="small" />-->
|
||||
<el-option label="大" value="big" />
|
||||
</el-select>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<template v-if="childItem.fontWeight">
|
||||
<template v-if="childItem.fontWeight">
|
||||
|
||||
<div class="flex mr-[30px]">
|
||||
<div class="leading-[30px] w-[50px] text-center text-[#707070] bg-[#d7d7d7] border-1 border-solid border-[#ededed]">粗细</div>
|
||||
<el-select v-model="formData.value[item.key][childItem.key].fontWeight" class="!w-[130px]">
|
||||
<el-option label="正常" value="normal" />
|
||||
<el-option label="加粗" value="bold" />
|
||||
</el-select>
|
||||
</div>
|
||||
</template>
|
||||
<div class="flex mr-[30px]">
|
||||
<div class="leading-[30px] w-[50px] text-center text-[#707070] bg-[#d7d7d7] border-1 border-solid border-[#ededed]">粗细</div>
|
||||
<el-select v-model="formData.value[item.key][childItem.key].fontWeight" class="!w-[130px]">
|
||||
<el-option label="正常" value="normal" />
|
||||
<el-option label="加粗" value="bold" />
|
||||
</el-select>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="childItem.remark" class="text-[12px] text-[#b2b2b2] mt-[10px]">{{ childItem.remark }}</div>
|
||||
<div v-if="childItem.remark" class="text-[12px] text-[#b2b2b2] mt-[10px]">{{ childItem.remark }}</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</el-card>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
|
||||
<el-card class="box-card !border-none w-[450px]" shadow="never">
|
||||
<el-card class="box-card !border-none w-[450px]" shadow="never">
|
||||
|
||||
<h3 class="panel-title !text-sm">{{ t('preview') }}</h3>
|
||||
<h3 class="panel-title !text-sm">{{ t('preview') }}</h3>
|
||||
|
||||
<!-- 动态加载组件 -->
|
||||
<component :is="modules[previewPath]" :value="formData.value"/>
|
||||
<!-- 动态加载组件 -->
|
||||
<component :is="modules[previewPath]" :value="formData.value" />
|
||||
|
||||
</el-card>
|
||||
</el-card>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</el-form>
|
||||
</el-form>
|
||||
|
||||
<div class="fixed-footer-wrap">
|
||||
<div class="fixed-footer">
|
||||
<el-button type="primary" :loading="repeat" @click="confirm(formRef)">{{ t('save') }}</el-button>
|
||||
<el-button @click="back()">{{ t('cancel') }}</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fixed-footer-wrap">
|
||||
<div class="fixed-footer">
|
||||
<el-button type="primary" :loading="repeat" @click="confirm(formRef)">{{ t('save') }}</el-button>
|
||||
<el-button @click="back()">{{ t('cancel') }}</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, computed } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { FormInstance, ElMessage } from 'element-plus'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { getPrinterType, addPrinterTemplate, editPrinterTemplate, getPrinterTemplateInfo } from '@/app/api/printer'
|
||||
import { ref, reactive, computed } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { FormInstance, ElMessage } from 'element-plus'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { getPrinterType, addPrinterTemplate, editPrinterTemplate, getPrinterTemplateInfo } from '@/app/api/printer'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const pageName = route.meta.title
|
||||
const repeat = ref(false)
|
||||
const loading = ref(true)
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const pageName = route.meta.title
|
||||
const repeat = ref(false)
|
||||
const loading = ref(true)
|
||||
|
||||
/**
|
||||
* 表单数据
|
||||
*/
|
||||
const initialFormData:any = {
|
||||
template_id: route.query.template_id || 0,
|
||||
template_type: '',
|
||||
template_name: '',
|
||||
value: {},
|
||||
/**
|
||||
* 表单数据
|
||||
*/
|
||||
const initialFormData: any = {
|
||||
template_id: route.query.template_id || 0,
|
||||
template_type: '',
|
||||
template_name: '',
|
||||
value: {},
|
||||
}
|
||||
|
||||
const formData: Record<string, any> = reactive({ ...initialFormData })
|
||||
|
||||
const formRef = ref<FormInstance>()
|
||||
|
||||
// 表单验证规则
|
||||
const formRules = computed(() => {
|
||||
return {
|
||||
template_name: [
|
||||
{ required: true, message: t('templateNamePlaceholder'), trigger: 'blur' },
|
||||
],
|
||||
template_type: [
|
||||
{ required: true, message: t('templateTypePlaceholder'), trigger: 'blur' },
|
||||
]
|
||||
}
|
||||
})
|
||||
|
||||
const formData: Record<string, any> = reactive({ ...initialFormData })
|
||||
// 动态加载组件
|
||||
const modulesFiles = import.meta.glob('./components/*.vue', { eager: true })
|
||||
const addonModulesFiles = import.meta.glob('@/addon/**/views/printer/components/*.vue', { eager: true })
|
||||
addonModulesFiles && Object.assign(modulesFiles, addonModulesFiles)
|
||||
|
||||
const formRef = ref<FormInstance>()
|
||||
const modules: any = {}
|
||||
for (const [key, value] of Object.entries(modulesFiles)) {
|
||||
const moduleName: any = key.split('/').pop()
|
||||
const name = moduleName.split('.')[0]
|
||||
modules[name] = value.default
|
||||
}
|
||||
|
||||
// 表单验证规则
|
||||
const formRules = computed(() => {
|
||||
return {
|
||||
template_name: [
|
||||
{ required: true, message: t('templateNamePlaceholder'), trigger: 'blur' },
|
||||
],
|
||||
template_type: [
|
||||
{ required: true, message: t('templateTypePlaceholder'), trigger: 'blur' },
|
||||
]
|
||||
const previewPath = ref('')
|
||||
const printerType: any = ref([])
|
||||
const template: any = ref([])
|
||||
|
||||
const init = async() => {
|
||||
await getPrinterType({}).then((res: any) => {
|
||||
if (res.data && res.data.length) {
|
||||
printerType.value = res.data;
|
||||
handlePrintType(printerType.value[0].key, Boolean(parseInt(formData.template_id)));
|
||||
}
|
||||
if (!formData.template_id) {
|
||||
loading.value = false
|
||||
}
|
||||
})
|
||||
|
||||
// 动态加载组件
|
||||
const modulesFiles = import.meta.glob('./components/*.vue', { eager: true })
|
||||
const addonModulesFiles = import.meta.glob('@/addon/**/views/printer/components/*.vue', { eager: true })
|
||||
addonModulesFiles && Object.assign(modulesFiles, addonModulesFiles)
|
||||
|
||||
const modules:any = {}
|
||||
for (const [key, value] of Object.entries(modulesFiles)) {
|
||||
const moduleName:any = key.split('/').pop()
|
||||
const name = moduleName.split('.')[0]
|
||||
modules[name] = value.default
|
||||
}
|
||||
|
||||
const previewPath = ref('')
|
||||
const printerType:any = ref([])
|
||||
const template:any = ref([])
|
||||
|
||||
const init = async ()=> {
|
||||
await getPrinterType({}).then((res: any) => {
|
||||
if (res.data && res.data.length) {
|
||||
printerType.value = res.data;
|
||||
handlePrintType(printerType.value[0].key, Boolean(parseInt(formData.template_id)));
|
||||
}
|
||||
if (!formData.template_id) {
|
||||
loading.value = false
|
||||
}
|
||||
})
|
||||
|
||||
if(formData.template_id) {
|
||||
getPrinterTemplateInfo(formData.template_id).then((res:any)=>{
|
||||
let data = res.data;
|
||||
if (data && Object.keys(data).length) {
|
||||
Object.keys(formData).forEach((key: string) => {
|
||||
if (key == 'value') {
|
||||
for (let ck in formData[key]){
|
||||
Object.assign(formData[key][ck],data[key][ck])
|
||||
}
|
||||
} else {
|
||||
formData[key] = data[key]
|
||||
}
|
||||
})
|
||||
loading.value = false
|
||||
}else {
|
||||
ElMessage({
|
||||
type: 'warning',
|
||||
duration: 1500,
|
||||
message: t('printTemplateEmpty')
|
||||
})
|
||||
setTimeout(()=>{
|
||||
back();
|
||||
loading.value = false
|
||||
}, 2000);
|
||||
}
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
init();
|
||||
|
||||
// 切换模板类型
|
||||
const handlePrintType = (value: any, load: boolean = false) => {
|
||||
for (let i = 0; i < printerType.value.length; i++) {
|
||||
if (printerType.value[i].key == value) {
|
||||
formData.template_type = printerType.value[i].key;
|
||||
previewPath.value = printerType.value[i].path;
|
||||
template.value = printerType.value[i].template;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 清空模板内容数据
|
||||
for (let key in formData.value) {
|
||||
delete formData.value[key];
|
||||
}
|
||||
|
||||
refreshTemplateData();
|
||||
}
|
||||
|
||||
// 刷新模板内容数据
|
||||
const refreshTemplateData = ()=> {
|
||||
for (let i = 0; i < template.value.length; i++) {
|
||||
let item: any = template.value[i];
|
||||
formData.value[item.key] = {};
|
||||
for (let k = 0; k < item.list.length; k++) {
|
||||
let childItem = item.list[k];
|
||||
formData.value[item.key][childItem.key] = {
|
||||
type: childItem.type,
|
||||
value: childItem.value,
|
||||
status: childItem.status,
|
||||
fontSize: childItem.fontSize,
|
||||
fontWeight: childItem.fontWeight,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 确认
|
||||
* @param formEl
|
||||
*/
|
||||
const confirm = async(formEl: FormInstance | undefined) => {
|
||||
if (loading.value || !formEl) return
|
||||
|
||||
if (printerType.value.length == 0) {
|
||||
ElMessage({
|
||||
type: 'warning',
|
||||
message: t('printTypeEmpty')
|
||||
})
|
||||
return;
|
||||
}
|
||||
|
||||
let save = formData.template_id ? editPrinterTemplate : addPrinterTemplate
|
||||
|
||||
await formEl.validate(async(valid) => {
|
||||
if (valid) {
|
||||
|
||||
let validateFlag = false;
|
||||
let validateMessage = '';
|
||||
|
||||
for (let i = 0; i < template.value.length; i++) {
|
||||
|
||||
let item: any = template.value[i];
|
||||
let isFail = false;
|
||||
|
||||
for (let k = 0; k < item.list.length; k++) {
|
||||
let childItem = item.list[k];
|
||||
if (formData.value[item.key][childItem.key].status == 0) {
|
||||
continue;
|
||||
}
|
||||
if (childItem.type == 'input') {
|
||||
if (formData.value[item.key][childItem.key].value == '') {
|
||||
validateFlag = true;
|
||||
validateMessage = `请输入${ childItem.label }`;
|
||||
isFail = true;
|
||||
break;
|
||||
}
|
||||
} else if (childItem.type == 'select') {
|
||||
if (formData.value[item.key][childItem.key].value == '') {
|
||||
validateFlag = true;
|
||||
validateMessage = `${ childItem.label }未设置[${ childItem.text }]`;
|
||||
isFail = true;
|
||||
break;
|
||||
}
|
||||
if (formData.template_id) {
|
||||
getPrinterTemplateInfo(formData.template_id).then((res: any) => {
|
||||
let data = res.data;
|
||||
if (data && Object.keys(data).length) {
|
||||
Object.keys(formData).forEach((key: string) => {
|
||||
if (key == 'value') {
|
||||
for (let ck in formData[key]) {
|
||||
Object.assign(formData[key][ck], data[key][ck])
|
||||
}
|
||||
} else {
|
||||
formData[key] = data[key]
|
||||
}
|
||||
|
||||
// 防止重复循环
|
||||
if (isFail) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (validateFlag) {
|
||||
ElMessage({
|
||||
type: 'warning',
|
||||
message: validateMessage
|
||||
})
|
||||
return;
|
||||
}
|
||||
|
||||
for (let i = 0; i < template.value.length; i++) {
|
||||
|
||||
let item: any = template.value[i];
|
||||
|
||||
for (let k = 0; k < item.list.length; k++) {
|
||||
let childItem = item.list[k];
|
||||
if (childItem.type == 'checkbox') {
|
||||
if (formData.value[item.key][childItem.key].value.length) {
|
||||
formData.value[item.key][childItem.key].status = 1;
|
||||
} else {
|
||||
formData.value[item.key][childItem.key].status = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (repeat.value) return
|
||||
repeat.value = true
|
||||
|
||||
let data = formData
|
||||
|
||||
save(data).then(res => {
|
||||
repeat.value = false
|
||||
if (!formData.template_id) {
|
||||
back()
|
||||
}
|
||||
}).catch(err => {
|
||||
repeat.value = false
|
||||
})
|
||||
loading.value = false
|
||||
} else {
|
||||
ElMessage({
|
||||
type: 'warning',
|
||||
duration: 1500,
|
||||
message: t('printTemplateEmpty')
|
||||
})
|
||||
setTimeout(() => {
|
||||
back();
|
||||
loading.value = false
|
||||
}, 2000);
|
||||
}
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
const back = () => {
|
||||
router.push('/printer/template/list')
|
||||
init();
|
||||
|
||||
// 切换模板类型
|
||||
const handlePrintType = (value: any, load: boolean = false) => {
|
||||
for (let i = 0; i < printerType.value.length; i++) {
|
||||
if (printerType.value[i].key == value) {
|
||||
formData.template_type = printerType.value[i].key;
|
||||
previewPath.value = printerType.value[i].path;
|
||||
template.value = printerType.value[i].template;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 清空模板内容数据
|
||||
for (let key in formData.value) {
|
||||
delete formData.value[key];
|
||||
}
|
||||
|
||||
refreshTemplateData();
|
||||
}
|
||||
|
||||
// 刷新模板内容数据
|
||||
const refreshTemplateData = () => {
|
||||
for (let i = 0; i < template.value.length; i++) {
|
||||
let item: any = template.value[i];
|
||||
formData.value[item.key] = {};
|
||||
for (let k = 0; k < item.list.length; k++) {
|
||||
let childItem = item.list[k];
|
||||
formData.value[item.key][childItem.key] = {
|
||||
type: childItem.type,
|
||||
value: childItem.value,
|
||||
status: childItem.status,
|
||||
fontSize: childItem.fontSize,
|
||||
fontWeight: childItem.fontWeight,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 确认
|
||||
* @param formEl
|
||||
*/
|
||||
const confirm = async(formEl: FormInstance | undefined) => {
|
||||
if (loading.value || !formEl) return
|
||||
|
||||
if (printerType.value.length == 0) {
|
||||
ElMessage({
|
||||
type: 'warning',
|
||||
message: t('printTypeEmpty')
|
||||
})
|
||||
return;
|
||||
}
|
||||
|
||||
let save = formData.template_id ? editPrinterTemplate : addPrinterTemplate
|
||||
|
||||
await formEl.validate(async(valid) => {
|
||||
if (valid) {
|
||||
|
||||
let validateFlag = false;
|
||||
let validateMessage = '';
|
||||
|
||||
for (let i = 0; i < template.value.length; i++) {
|
||||
|
||||
let item: any = template.value[i];
|
||||
let isFail = false;
|
||||
|
||||
for (let k = 0; k < item.list.length; k++) {
|
||||
let childItem = item.list[k];
|
||||
if (formData.value[item.key][childItem.key].status == 0) {
|
||||
continue;
|
||||
}
|
||||
if (childItem.type == 'input') {
|
||||
if (formData.value[item.key][childItem.key].value == '') {
|
||||
validateFlag = true;
|
||||
validateMessage = `请输入${ childItem.label }`;
|
||||
isFail = true;
|
||||
break;
|
||||
}
|
||||
} else if (childItem.type == 'select') {
|
||||
if (formData.value[item.key][childItem.key].value == '') {
|
||||
validateFlag = true;
|
||||
validateMessage = `${ childItem.label }未设置[${ childItem.text }]`;
|
||||
isFail = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 防止重复循环
|
||||
if (isFail) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (validateFlag) {
|
||||
ElMessage({
|
||||
type: 'warning',
|
||||
message: validateMessage
|
||||
})
|
||||
return;
|
||||
}
|
||||
|
||||
for (let i = 0; i < template.value.length; i++) {
|
||||
|
||||
let item: any = template.value[i];
|
||||
|
||||
for (let k = 0; k < item.list.length; k++) {
|
||||
let childItem = item.list[k];
|
||||
if (childItem.type == 'checkbox') {
|
||||
if (formData.value[item.key][childItem.key].value.length) {
|
||||
formData.value[item.key][childItem.key].status = 1;
|
||||
} else {
|
||||
formData.value[item.key][childItem.key].status = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (repeat.value) return
|
||||
repeat.value = true
|
||||
|
||||
let data = formData
|
||||
|
||||
save(data).then(res => {
|
||||
repeat.value = false
|
||||
if (!formData.template_id) {
|
||||
back()
|
||||
}
|
||||
}).catch(err => {
|
||||
repeat.value = false
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const back = () => {
|
||||
router.push('/printer/template/list')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@ -68,6 +68,7 @@ import { t } from '@/lang'
|
||||
import { getPrinterTemplatePageList, deletePrinterTemplate,getPrinterType } from '@/app/api/printer'
|
||||
import { ElMessageBox,FormInstance } from 'element-plus'
|
||||
import { useRoute,useRouter } from 'vue-router'
|
||||
import { setTablePageStorage,getTablePageStorage } from "@/utils/common";
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
@ -113,11 +114,12 @@ const loadPrinterTemplateList = (page: number = 1) => {
|
||||
printerTemplateTable.loading = false
|
||||
printerTemplateTable.data = res.data.data
|
||||
printerTemplateTable.total = res.data.total
|
||||
setTablePageStorage(printerTemplateTable.page, printerTemplateTable.limit, printerTemplateTable.searchParam);
|
||||
}).catch(() => {
|
||||
printerTemplateTable.loading = false
|
||||
})
|
||||
}
|
||||
loadPrinterTemplateList()
|
||||
loadPrinterTemplateList(getTablePageStorage(printerTemplateTable.searchParam).page)
|
||||
|
||||
/**
|
||||
* 添加小票打印模板
|
||||
|
||||
@ -154,7 +154,6 @@ const cancel = () => {
|
||||
}
|
||||
|
||||
const setFormData = async (data: any = null) => {
|
||||
console.log(data)
|
||||
initData.value = cloneDeep(data)
|
||||
loading.value = true
|
||||
Object.assign(formData, initialFormData)
|
||||
|
||||
@ -81,11 +81,7 @@ setFormData()
|
||||
const formRef = ref<FormInstance>()
|
||||
|
||||
// 表单验证规则
|
||||
const formRules = reactive<FormRules>({
|
||||
site_name: [
|
||||
{ required: true, message: t('siteNamePlaceholder'), trigger: 'blur' }
|
||||
]
|
||||
})
|
||||
const formRules = reactive<FormRules>({})
|
||||
|
||||
/**
|
||||
* 保存
|
||||
|
||||
@ -83,7 +83,7 @@ import { t } from '@/lang'
|
||||
import { img } from '@/utils/common'
|
||||
import { getExportStatusList, getExportKeyList, getExportList, deleteExport } from '@/app/api/sys'
|
||||
import { ElMessageBox, FormInstance } from 'element-plus'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
const route = useRoute()
|
||||
const pageName = route.meta.title
|
||||
@ -141,8 +141,6 @@ const loadExportList = (page: number = 1) => {
|
||||
}
|
||||
loadExportList()
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
/**
|
||||
* 下载导出报表
|
||||
*/
|
||||
@ -168,7 +166,6 @@ const deleteEvent = (id: number) => {
|
||||
).then(() => {
|
||||
deleteExport(id).then(() => {
|
||||
loadExportList()
|
||||
}).catch(() => {
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user