Commit 3148d2be by linjinhong

Merge remote-tracking branch 'origin/lin-task' into dev

parents 57ead639 3c4b33a9
......@@ -21,6 +21,7 @@ declare module 'vue' {
ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
ElDialog: typeof import('element-plus/es')['ElDialog']
ElDivider: typeof import('element-plus/es')['ElDivider']
ElDrawer: typeof import('element-plus/es')['ElDrawer']
ElDropdown: typeof import('element-plus/es')['ElDropdown']
ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
......
......@@ -2,11 +2,11 @@ import { BasePaginationData, BaseRespData } from '@/types/api'
import axios from './axios'
import { ExternalAuthListData } from '@/types/api/externalAuth'
export function getExternalAuthorisationListApi(
data: {
type: string
data?: {
type?: string
},
page: number,
pageSize: number,
page?: number,
pageSize?: number,
) {
return axios.post<never, BasePaginationData<ExternalAuthListData>>(
'factory/baseExternalAccount/list_page',
......@@ -36,6 +36,12 @@ export function deleteExternalAuthorisationApi(ids: string) {
`factory/baseExternalAccount/delete?ids=${ids}`,
)
}
export function baseExternalAccountLogsApi(params: { ids: string }) {
return axios.get<never, BaseRespData<never>>(
`factory/baseExternalAccount/logs`,
{ params },
)
}
export function addExternalAuthorisationApi(
url: string,
data: ExternalAuthListData,
......
......@@ -553,3 +553,13 @@ export function completeDeliveryApi(params: {
params,
)
}
// 物流轨迹
export function get17TrackInfoApi(params: { id: string | number }) {
return axios.get(`factory/podJomallOrderUs/get17TrackInfo`, { params })
}
// 获取riin 权限
export function getAccountCodeByFactoryIdApi(params: { token: string }) {
return axios.get(`factory/baseExternalAccount/getAccountCodeByFactoryId`, {
params,
})
}
......@@ -7,13 +7,18 @@ import './styles/index.scss'
import VxeUITable from 'vxe-table'
import 'vxe-table/lib/style.css'
import { isPermissionBtn } from '@/utils/index'
// 确保在渲染用户提供的HTML内容时,不会执行任何潜在的恶意脚本,从而提高应用的安全性
import vueDomPurifyHTMLPlugin from 'vue-dompurify-html'
createApp(App)
const app = createApp(App)
app
.use(vueDomPurifyHTMLPlugin)
.use(router)
.use(store)
.use(VxeUITable)
.mount('#app')
app.config.globalProperties.$isPermissionBtn = isPermissionBtn
......@@ -256,6 +256,13 @@ const router = createRouter({
},
component: WarehousePosition,
},
{
path: '/setting/settingIndex',
meta: {
title: '设置',
},
component: () => import('@/views/setting/settingIndex.vue'),
},
],
},
// 登录
......
......@@ -192,6 +192,11 @@ const menu: MenuItem[] = [
},
],
},
{
index: '/setting/settingIndex',
id: 7,
label: '设置',
},
// {
// index: '',
......
import { defineStore } from 'pinia'
const usePermissionBtnStore = defineStore('permissionBtn', {
state: () => ({
permissionBtns: [] as string[], // 权限按钮数组
}),
actions: {
setBtn(state: string[]) {
this.permissionBtns = state
},
},
})
export default usePermissionBtnStore
......@@ -30,8 +30,15 @@ const useUserStore = defineStore('user', {
async login(data: LoginReq) {
try {
const resp = await loginApi(data)
console.log(33, resp)
this.setUser(resp.data.sysUser)
setToken(resp.data.token)
localStorage.setItem(
'baseExternalAccountTypes',
JSON.stringify(resp.data.sysUser.baseExternalAccountTypes),
)
router.push({ path: '/dashboard' })
} catch (error) {
// showError(error)
......
......@@ -24,6 +24,7 @@ export interface SysUser {
factoryCode: string
status: number
factory: Factory
baseExternalAccountTypes?: []
}
export interface Factory {
......@@ -36,4 +37,4 @@ export interface Factory {
goodsNumber: number
authorizeNumber: number
status: number
}
\ No newline at end of file
}
......@@ -16,4 +16,5 @@ export interface ExternalAuthListData {
token?: string
refreshToken?: string
refreshTokenFailureTime?: string
enable?: boolean
}
import { get } from 'lodash-es'
import { ElMessage } from 'element-plus'
import { DateTime } from 'luxon'
import usePermissionBtnStore from '@/store/permission'
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function val<T>(data: T, key: string | ((data: T) => any)) {
if (typeof key === 'function') return key(data)
......@@ -40,3 +42,10 @@ export function convertToChinaTime(
const chinaTime = inputTime.setZone(targetZone)
return chinaTime.toFormat('yyyy-MM-dd HH:mm:ss')
}
export function isPermissionBtn(key: string) {
const permissionBtns = usePermissionBtnStore().permissionBtns
if (!permissionBtns) return false
return permissionBtns.includes(key)
}
......@@ -381,7 +381,9 @@
</ElButton>
</span>
</ElFormItem>
<ElFormItem v-if="status === 'TO_BE_CONFIRMED'">
<ElFormItem
v-if="status === 'TO_BE_CONFIRMED' && isPermissionBtn('RIIN')"
>
<span class="item">
<ElButton type="success" @click="confirmProductToRiin">
转至锐印生产
......@@ -519,6 +521,7 @@
<ElButton type="warning" @click="arrangeFinish">排单完成</ElButton>
</span>
</ElFormItem>
<ElFormItem
v-if="status !== 'BATCH_DOWNLOAD' && status !== 'WAIT_SHIPMENT'"
>
......@@ -1530,6 +1533,17 @@
刷新地址
</ElButton>
</span>
<span
v-if="
(status === 'IN_TRANSIT' || status === 'COMPLETE') &&
isPermissionBtn('TRACK')
"
class="operate-item"
>
<ElButton link type="primary" @click="logTrajectory(row)"
>物流轨迹</ElButton
>
</span>
</div>
</template>
</TableView>
......@@ -2283,6 +2297,21 @@
<el-dialog v-model="dialogVisible" width="35%">
<img :src="dialogImageUrl" alt="商品预览图片" />
</el-dialog>
<el-dialog title="物流轨迹" v-model="timeLineVisible" width="1000px">
<el-timeline>
<el-timeline-item
v-for="(item, index) in timeLine"
:key="index"
:timestamp="item.time_utc"
placement="top"
:type="index == 0 ? 'primary' : ''"
>
<el-card>
{{ item.description }}
</el-card>
</el-timeline-item>
</el-timeline>
</el-dialog>
</template>
<script setup lang="ts">
import { getUserMarkList } from '@/api/common'
......@@ -2350,6 +2379,8 @@ import {
rejectToApi,
statusPushApi,
completeDeliveryApi,
get17TrackInfoApi,
getAccountCodeByFactoryIdApi,
} from '@/api/podUsOrder'
import { BaseRespData } from '@/types/api'
......@@ -2390,6 +2421,9 @@ import RightClickMenu from '@/components/RightClickMenu.vue'
import ResultInfo from './components/ResultInfo.vue'
import { isArray, isString } from '@/utils/validate'
import platformJson from '../../../json/platform.json'
import { getToken } from '@/api/axios'
import usePermissionBtnStore from '@/store/permission'
const permissionBtns = usePermissionBtnStore()
import {
useRouter,
type NavigationGuardNext,
......@@ -3857,6 +3891,24 @@ const arrangeFinish = async () => {
loading.close()
}
}
interface timeLineType {
time_iso?: string
time_utc?: string
description?: string
}
const timeLineVisible = ref(false)
const timeLine = ref<timeLineType[]>([])
const logTrajectory = async (row: { id: string }) => {
const { data } = await get17TrackInfoApi({ id: row.id })
const res = data.accepted[0]?.track_info?.tracking
timeLine.value = res?.providers[0]?.events
// if (data.rejected?.length) {
// console.log(data.rejected[0].error.message)
// throw Error(data.rejected[0].error.message)
// }
timeLineVisible.value = true
}
const logList = ref<LogListData[]>([])
const logVisible = ref(false)
const operationLog = async (id: number, e: MouseEvent | null) => {
......@@ -4977,6 +5029,17 @@ function changeChinaTime(zone: string) {
})
}
const token = getToken() as string
async function getPermission() {
const res = await getAccountCodeByFactoryIdApi({ token })
permissionBtns.setBtn(res.data)
console.log(res)
}
getPermission()
const globalProperties =
getCurrentInstance()?.appContext.config.globalProperties // 获取全局挂载
const isPermissionBtn = globalProperties?.$isPermissionBtn
useRouter().beforeEach((to, from, next) => {
handleBeforeRouteLeave(to, from, next)
})
......@@ -5323,6 +5386,11 @@ useRouter().beforeEach((to, from, next) => {
}
.el-timeline-item__wrapper {
padding-left: 15px;
top: -6px;
top: -4px;
}
.el-timeline
> .el-timeline-item:first-child
.el-timeline-item__timestamp.is-top {
color: #409eff;
}
</style>
<template>
<div
class="user-page flex-column card h-100 overflow-hidden"
style="position: relative"
>
<div class="card-header">
<span>系统配置</span>
</div>
<div class="cardBox">
<div v-for="(item, index) in formList" style="width: 600px" :key="index">
<el-form
v-if="item.type === 'RIIN'"
class="form"
ref="formRef"
label-width="120"
:model="item"
>
<div class="formBox">
<el-form-item label="转至RIIN生产">
<el-switch
v-model="item.enable"
class="ml-2"
style="--el-switch-on-color: #42b983"
/>
</el-form-item>
<div class="formContent" v-if="item.enable">
<el-form-item
label="账号"
prop="appKey"
:rules="[{ required: true, message: '请输入RIIN账号' }]"
>
<ElInput
ref="productionOrderRef"
v-model="item.appKey"
placeholder="请输入RIIN账号"
clearable
style="width: 100%"
/></el-form-item>
<el-form-item
label="App Secret"
prop="appSecret"
:rules="[{ required: true, message: '请输入App Secret' }]"
>
<ElInput
ref="productionOrderRef"
v-model="item.appSecret"
placeholder="请输入App Secret"
clearable
style="width: 100%"
/></el-form-item>
</div>
</div>
<ElButton
class="btn"
color="#42b983"
@click="saveConfiguration(item, index)"
>保存配置</ElButton
>
</el-form>
<el-form
v-if="item.type === 'TRACK'"
class="form"
ref="formRef"
label-width="120"
:model="item"
>
<div class="formBox">
<el-form-item label="物流轨迹跟踪">
<el-switch
v-model="item.enable"
class="ml-2"
style="--el-switch-on-color: #42b983"
/>
</el-form-item>
<div class="formContent" v-if="item.enable">
<el-form-item
label="17Track账号"
prop="appKey"
:rules="[{ required: true, message: '请输入17Track账号' }]"
>
<ElInput
ref="productionOrderRef"
v-model="item.appKey"
placeholder="请输入17Track账号"
clearable
style="width: 100%"
/></el-form-item>
<el-form-item
label="账号Token"
prop="token"
:rules="[{ required: true, message: '请输入账号Token' }]"
>
<ElInput
ref="productionOrderRef"
v-model="item.token"
placeholder="请输入账号Token"
clearable
style="width: 100%"
/></el-form-item>
</div>
</div>
<ElButton
class="btn"
color="#42b983"
@click="saveConfiguration(item, index)"
>保存配置</ElButton
>
</el-form>
</div>
</div>
<div class="logBox">
<div>操作日志</div>
<LogList :log-list="logList" style="font-size: 14px; height: 100%" />
</div>
</div>
</template>
<script setup lang="ts">
import {
addExternalAuthorisationApi,
getExternalAuthorisationListApi,
baseExternalAccountLogsApi,
} from '@/api/externalAuth'
import { ExternalAuthListData } from '@/types/api/externalAuth'
interface formType {
id?: number
enable?: boolean
appKey?: string
appSecret?: string
type?: string
}
const formRef = ref()
const logList = ref([])
async function saveConfiguration(item: formType, index: number) {
let loading
try {
await formRef.value[index]?.validate()
const params = { ...item }
const url = !params.id
? 'factory/baseExternalAccount/add'
: 'factory/baseExternalAccount/update'
loading = ElLoading.service({
fullscreen: true,
text: '操作中...',
background: 'rgba(0, 0, 0, 0.3)',
})
const res = await addExternalAuthorisationApi(url, params)
console.log(res)
// ElMessage.success('保存配置成功')
await ElMessageBox.confirm('保存配置成功!!需重新登录才能生效', '提示', {
confirmButtonText: '确定',
showCancelButton: false,
type: 'success',
})
await getDetail()
handleClick()
} catch (error) {
console.log(error)
} finally {
loading?.close()
}
}
const formList = ref<ExternalAuthListData[]>([])
async function getDetail() {
let loading
try {
loading = ElLoading.service({
fullscreen: true,
text: '操作中...',
background: 'rgba(0, 0, 0, 0.3)',
})
const res = await getExternalAuthorisationListApi({}, 1, 100)
const records = res.data.records || []
const newArr = records.filter((el) => el.type)
const typeSet = new Set(newArr.map((el) => el.type))
const hasRIIN = typeSet.has('RIIN')
const hasTRACK = typeSet.has('TRACK')
if (newArr.length === 0) {
formList.value = [{ type: 'RIIN' }, { type: 'TRACK' }]
} else {
const result = [...newArr]
if (!hasRIIN) result.push({ type: 'RIIN' })
if (!hasTRACK) result.push({ type: 'TRACK' })
formList.value = result
}
console.log('Form list:', formList.value)
} catch (error) {
console.error('Failed to get external authorizations:', error)
} finally {
loading?.close()
}
}
async function handleClick() {
try {
let ids = ''
const idList = formList.value.map((el) => el.id).filter((el) => el)
console.log(222, idList)
if (idList.length) {
ids = idList.join(',')
}
console.log(205, ids)
const res = await baseExternalAccountLogsApi({
ids,
})
logList.value = res.data
console.log(res)
} catch (error) {
console.log(error)
}
}
onMounted(async () => {
await getDetail()
handleClick()
})
</script>
<style lang="scss" scoped>
.card-header {
margin-left: 200px;
font-size: 30px;
margin-bottom: 20px;
}
:deep() {
.demo-tabs {
height: calc(100% - 60px);
}
.cardBox {
flex: 3;
overflow-y: scroll;
height: 100%;
.el-card__footer {
border: none !important;
}
.formBox {
width: 100%;
margin-bottom: 15px;
padding: 20px;
border: 1px solid #ebebeb;
border-radius: 8px;
&:last-child {
margin-bottom: 0;
}
.formContent {
padding: 20px;
background-color: #f9f9f9;
border-radius: 5px;
.el-form-item:last-child {
margin-bottom: 0 !important;
}
}
}
.btn {
color: #fff;
}
}
.logBox {
border-top: 1px solid #ebebeb;
padding-top: 10px;
height: 150px;
}
.form {
margin-bottom: 15px;
}
}
</style>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment