Commit 9c8ec360 by wuqian

Merge branch 'dev' of 47.122.114.111:qinjianhui/factory_front into new-pod-cn

parents 6d3b965d 7a0fd357
......@@ -12,7 +12,8 @@
"rules": {
"vue/require-default-prop": "off",
"vue/multi-word-component-names": "off",
"no-console": "off","no-unused-vars": "off",
"no-console": "off",
"@typescript-eslint/no-explicit-any": "error"
},
"overrides": [{ "files": "*.vue", "rules": { "no-undef": "off" } }]
}
......@@ -32,7 +32,6 @@ declare module 'vue' {
ElImage: typeof import('element-plus/es')['ElImage']
ElInput: typeof import('element-plus/es')['ElInput']
ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
ElLink: typeof import('element-plus/es')['ElLink']
ElMenu: typeof import('element-plus/es')['ElMenu']
ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
ElOption: typeof import('element-plus/es')['ElOption']
......@@ -65,6 +64,7 @@ declare module 'vue' {
RouterView: typeof import('vue-router')['RouterView']
Select: typeof import('./src/components/Form/Select.vue')['default']
ShipmentOrderDetail: typeof import('./src/components/ShipmentOrderDetail.vue')['default']
SideBar: typeof import('./src/components/SideBar.vue')['default']
SplitDiv: typeof import('./src/components/splitDiv/splitDiv.vue')['default']
'Switch ': typeof import('./src/components/Form/Switch .vue')['default']
TableView: typeof import('./src/components/TableView.vue')['default']
......
import { BaseRespData } from '@/types/api'
import axios from './axios'
import { LogisticsData } from '@/types/api/order'
import { LogisticBill } from '@/types/api/podMakeOrder'
import { userData } from '@/types/api/user'
import { VersionImageList } from '@/types/api/typesetting'
......@@ -36,14 +38,14 @@ export function uploadFileApi(data: FormData) {
// 打印物流面单 US
export function getLogisticUSApi(content: string) {
return axios.get<never, BaseRespData<{ documentUrl: string }>>(
`factory/podJomallOrderUs/getDocument?content=${content}`,
return axios.get<never, BaseRespData<LogisticBill>>(
`factory/podJomallOrderUs/getOrderByFactorySubOrderNumber?factorySubOrderNumber=${content}`,
)
}
// 打印物流面单 CN
export function getLogisticCNApi(content: string) {
return axios.get<never, BaseRespData<{ documentUrl: string }>>(
`factory/podJomallOrder/getDocument?content=${content}`,
return axios.get<never, BaseRespData<LogisticBill>>(
`factory/podJomallOrder/getOrderByThirdSubOrderNumber?thirdSubOrderNumber=${content}`,
)
}
......@@ -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,
......
......@@ -144,6 +144,12 @@ export function getUniuniList() {
},
)
}
// 获取tictok物流承运商
export function getTiktokCarrier() {
return axios.get<never, BaseRespData<{ name: string; id: number }[]>>(
'logisticsWay/getTiktokShippingProvider',
)
}
/**
* @description 发货地址
......
......@@ -425,7 +425,7 @@ export function arrangeFinishApi(ids: number[]) {
// 获取工艺
export function getListCraftApi() {
return axios.post<never, BaseRespData<never>>(
`factory/podJomallOrderProductUs/listCraft`,
`factory/podJomallOrderProductCn/listCraft`,
)
}
......
......@@ -544,3 +544,35 @@ 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,
})
}
// 打印拣货单item
export function printPickPdfByBatchNumberApi(params: {
batchArrangeNumber: string
}) {
return axios.get<never, BaseRespData<never>>(
`factory/podJomallOrderProductUs/printPickPdfByBatchNumber`,
{
params,
},
)
}
// 打印生产单item
export function printProductionPdfByBatchNumberApi(params: {
batchArrangeNumber: string
}) {
return axios.get<never, BaseRespData<never>>(
`factory/podJomallOrderProductUs/printProductionPdfByBatchNumber`,
{
params,
},
)
}
......@@ -76,36 +76,40 @@ import type { TypesettingListData } from '../types/api/typesetting'
// 定义通用字段接口,用于处理动态属性
interface CommonFields {
[key: string]: unknown;
variantImage?: string;
mainImage?: string;
sku?: string;
productName?: string;
[key: string]: unknown
variantImage?: string
mainImage?: string
sku?: string
productName?: string
}
// 定义图片列表项接口
interface ImageListItem {
[key: string]: unknown;
imagePath?: string;
[key: string]: unknown
imagePath?: string
}
// 创建一个工具类型,用于使用字符串索引访问对象属性
type IndexableObject = Record<string, unknown>;
type IndexableObject = Record<string, unknown>
// 扩展现有类型以确保它们有通用字段
type CardItem = PodProductList | CardOrderData | TypesettingListData | CommonFields;
type CardItem =
| PodProductList
| CardOrderData
| TypesettingListData
| CommonFields
// 定义 props 类型
interface Props {
cardItem: CardItem;
active?: boolean;
showSelectIcon?: boolean;
showSku?: boolean;
showProductInfo?: boolean;
showImageList?: boolean;
imageField?: string;
imageListField?: string;
imagePathField?: string;
cardItem: CardItem
active?: boolean
showSelectIcon?: boolean
showSku?: boolean
showProductInfo?: boolean
showImageList?: boolean
imageField?: string
imageListField?: string
imagePathField?: string
}
// 定义默认值
......@@ -122,45 +126,45 @@ const props = withDefaults(defineProps<Props>(), {
// 获取主图片源
const mainImageSrc = computed<string>(() => {
const item = props.cardItem as IndexableObject;
const item = props.cardItem as IndexableObject
// 使用索引访问避免联合类型的属性访问问题
if (
props.imageField === 'variantImage' &&
typeof item[props.imageField] === 'string'
) {
return item[props.imageField] as string;
return item[props.imageField] as string
}
if (
props.imageField === 'mainImage' &&
typeof item[props.imageField] === 'string'
) {
return item[props.imageField] as string;
return item[props.imageField] as string
}
// 默认返回空字符串
return '';
return ''
})
// 获取图片列表
const imageList = computed<ImageListItem[]>(() => {
const item = props.cardItem as IndexableObject;
const list = item[props.imageListField];
return Array.isArray(list) ? list as ImageListItem[] : [];
const item = props.cardItem as IndexableObject
const list = item[props.imageListField]
return Array.isArray(list) ? (list as ImageListItem[]) : []
})
// 判断是否有图片列表
const hasImageList = computed<boolean>(() => {
return imageList.value.length > 0;
return imageList.value.length > 0
})
// 获取图片列表项的图片路径
function getItemImagePath(item: IndexableObject): string {
return (item[props.imagePathField] as string) || '';
return (item[props.imagePathField] as string) || ''
}
const copy = (text: string) => {
navigator.clipboard.writeText(text);
ElMessage.success('复制成功');
navigator.clipboard.writeText(text)
ElMessage.success('复制成功')
}
</script>
......@@ -174,11 +178,16 @@ const copy = (text: string) => {
.commodity-card-image {
position: relative;
border: 1px solid #eee;
border-top-left-radius: 10px;
border-top-right-radius: 10px;
.img_top_left {
position: absolute;
top: 5px;
left: 5px;
display: flex;
align-items: center;
gap: 4px;
}
.img_top_right {
......
......@@ -34,6 +34,7 @@
</el-sub-menu>
</template>
</el-menu>
<SideBar />
<div v-if="userInfo" class="user-info">
<span class="user-avatar" style="color: #fff; font-size: 14px">
工厂: {{ userInfo.factoryCode }}
......@@ -111,19 +112,6 @@
<ArrowRight />
</el-icon>
</div>
<!-- 右侧工具栏 -->
<div class="tool_warper">
<div title="格式工具" class="tool-item" @click="formatDrawer = true">
<img src="../assets/images/brush-no.png" width="24" height="24" />
</div>
<div
title="打印物流面单"
class="tool-item"
@click="getLogisticDrawer = true"
>
<img src="../assets/images/printer.png" width="24" height="24" />
</div>
</div>
</div>
<el-dialog
v-model="dialogVisible"
......@@ -170,69 +158,6 @@
</span>
</template>
</el-dialog>
<span>
<el-drawer
v-model="formatDrawer"
class="format-drawer"
title="格式工具"
direction="rtl"
size="45%"
>
<el-input
v-model="textareaT"
style="width: 100%"
:rows="10"
type="textarea"
placeholder="请输入"
@input="confimTools"
/>
<div
style="
margin-top: 10px;
height: 250px;
overflow: auto;
border: 1px solid #ddd;
padding: 10px;
"
>
{{ newTextareaT }}
</div>
<template #footer>
<span style="display: flex; justify-content: center">
<el-button @click="formatDrawer = false"> 取 消 </el-button>
<el-button type="primary" @click="copy"> 拷 贝 </el-button>
</span>
</template>
</el-drawer>
<el-drawer
v-model="getLogisticDrawer"
direction="btt"
class="get-logistic-drawer"
title="打印物流面单"
@close="content = ''"
>
<ElSelect
v-model="sheetPrinter"
placeholder="请选择打印机"
@change="handlePrinterChange"
style="width: 200px; margin-right: 10px"
>
<ElOption
v-for="item in printDeviceList"
:key="item"
:label="item"
:value="item"
/>
</ElSelect>
<el-input
v-model="content"
placeholder="请输入单号"
style="width: 300px; margin-right: 10px"
clearable
/>
<el-button type="primary" @click="getLogistic">查 询</el-button>
</el-drawer>
</span>
</template>
<script setup lang="ts">
import {
......@@ -257,12 +182,12 @@ import userUserStore from '@/store/user'
import type { FormRules } from 'element-plus'
import { useValue } from '@/utils/hooks/useValue'
import useLodop from '@/utils/hooks/useLodop'
import { changePasswordApi } from '@/api/auth'
import { getLogisticUSApi, getLogisticCNApi } from '@/api/common'
import { filePath, FileCnPath } from '@/api/axios'
import { ElMessage } from 'element-plus'
import SideBar from './SideBar.vue'
interface MenuItem {
index: string
id: number
......@@ -287,14 +212,6 @@ const menuList = reactive(Menu)
const userStore = userUserStore()
const userInfo = userStore.user
const dialogVisible = ref(false)
const formatDrawer = ref(false)
const getLogisticDrawer = ref(false)
const printDeviceList = ref<string[]>([])
const sheetPrinter = ref('')
const textareaT = ref('')
const newTextareaT = ref('')
const content = ref('')
// 密码form
const [passwordForm, resetPasswordForm] = useValue<PasswordForm>(
{} as PasswordForm,
......@@ -486,102 +403,6 @@ const ensureActiveTabVisible = () => {
})
}
// 格式工具输入
const confimTools = (v: string) => {
// 先处理结尾的多个空格,只保留一个
let text = v.replace(/\s+$/, ' ')
// 处理开头的多个空格,只保留一个
text = text.replace(/^\s+/, ' ')
// 将多个连续空格替换为单个空格
text = text.replace(/\s+/g, ' ')
// 然后将所有空格和换行符替换为逗号
text = text.replace(/(\s|[\r\n])/g, ',')
// 如果结尾是逗号,则删除
if (text.slice(-1) === ',') {
newTextareaT.value = text.slice(0, -1)
} else {
newTextareaT.value = text
}
}
// 复制
const copy = () => {
const oInput = document.createElement('input')
oInput.value = newTextareaT.value
document.body.appendChild(oInput)
oInput.select() // 选择对象
document.execCommand('Copy') // 执行浏览器复制命令
oInput.className = 'oInput'
oInput.style.display = 'none'
document.body.removeChild(oInput)
ElMessage({
message: '复制成功',
type: 'success',
})
}
const { getCLodop } = useLodop()
const initPrintDevice = () => {
const lodop = getCLodop(null, null)
if (!lodop) return
const arr = []
// 获取打印机数量
const length = lodop.GET_PRINTER_COUNT()
for (let i = 0; i < length; i++) {
// 根据设备序号获取设备名
const name = lodop.GET_PRINTER_NAME(i)
arr.push(name)
}
// 获取默认打印机
sheetPrinter.value = lodop.GET_PRINTER_NAME(0)
printDeviceList.value = arr
}
// 处理打印机选择变化,保存到 localStorage
const handlePrinterChange = (value: string) => {
sheetPrinter.value = value
localStorage.setItem('sheetPrinter', JSON.stringify(value))
}
// 打印物流面单
const getLogistic = () => {
if (!content.value) {
ElMessage.warning('请输入单号')
return
}
// 按_分割字符串
const parts = content.value.split('_')
// 检查是否有足够的_分隔符
if (parts.length < 4) {
ElMessage.error('单号格式错误,请检查输入')
return
}
// 获取第三个_后面的内容
const thirdPart = parts[3]
if (thirdPart.startsWith('USPSC')) {
// 美国物流
getLogisticUSApi(content.value).then((res) => {
if (res.code === 200) {
window.open(filePath + res.data.documentUrl, '_blank')
}
})
} else if (thirdPart.startsWith('JMPSC')) {
// 中国物流
getLogisticCNApi(content.value).then((res) => {
if (res.code === 200) {
window.open(FileCnPath + res.data.documentUrl, '_blank')
}
})
} else {
ElMessage.error('单号格式错误,请检查输入')
}
}
// 监听路由变化,自动添加标签
watch(
() => route.path,
......@@ -591,24 +412,6 @@ watch(
{ immediate: true },
)
watch(getLogisticDrawer, async (value: boolean) => {
if (value) {
initPrintDevice()
const locaclPrinter = localStorage.getItem('sheetPrinter')
if (locaclPrinter) {
const savedPrinter = JSON.parse(locaclPrinter)
// 检查保存的打印机是否在当前打印机列表中
if (printDeviceList.value.includes(savedPrinter)) {
sheetPrinter.value = savedPrinter
} else {
// 如果保存的打印机不在当前列表中,清空 localStorage 并设置为空
localStorage.removeItem('sheetPrinter')
sheetPrinter.value = ''
}
}
}
})
// 点击标签时切换路由
watch(activeTab, (newTab) => {
if (newTab) {
......@@ -741,38 +544,4 @@ onUnmounted(() => {
display: flex;
align-items: center;
}
.tool_warper {
position: absolute;
top: 50px;
right: 0;
bottom: 0;
width: 40px;
background: #001529;
z-index: 999;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
::v-deep(.el-drawer.rtl) {
height: 650px !important;
right: 40px;
top: calc(50% - 325px) !important;
}
::v-deep(.get-logistic-drawer.el-drawer.btt) {
height: 120px !important;
width: 700px !important;
top: calc(50% - 60px) !important;
left: calc(50% - 350px) !important;
}
.tool-item {
width: 24px;
height: 24px;
cursor: pointer;
margin-bottom: 10px;
}
</style>
......@@ -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
......@@ -263,6 +263,13 @@ const router = createRouter({
},
component: WarehousePosition,
},
{
path: '/setting/settingIndex',
meta: {
title: '设置',
},
component: () => import('@/views/setting/settingIndex.vue'),
},
],
},
// 登录
......
......@@ -198,6 +198,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
}
......@@ -48,3 +48,22 @@ export interface ProductList {
podJomallCnNo?: string
previewImgs?: { sort: string | number; title: string; url: string }[]
}
export interface LogisticBill {
expressSheet?: string
salesPlatform?: string
orderStatus?: string
shopWay?: string
blocked?: boolean
logisticsCompanyName?: string
logisticsWayNameId?: string
shopNumber?: string
id?: string
shopId?: string
orderId?: string
orderNumber?: string
trackingNumber?: string
systemWeight?: number | string
purchaseNumber?: number
productList?: ProductList[]
}
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)
}
......@@ -81,6 +81,7 @@ import {
getLogisticsLog,
getLogisticsCompanyList,
getUniuniList,
getTiktokCarrier,
} from '@/api/logistics'
import { WarehouseListData } from '@/types/api/podUsOrder'
......@@ -401,25 +402,56 @@ const formConfig = computed<IFormConfig[]>(() => [
))}
</el-select>
</el-form-item>
<el-form-item
key={index}
class="renderItem"
label="物流名称"
style="display: flex;flex:50%"
prop={`platformList.${index}.logisticsName`}
rules={[
{
required: true,
message: '请输入物流名称',
trigger: 'blur',
},
]}
>
<el-input
v-model={item.logisticsName}
placeholder="请输入物流名称"
/>
</el-form-item>
{item['showPlatform'].length === 1 &&
item['showPlatform'][0] === 'TIKTOK' ? (
<el-form-item
key={index}
class="renderItem"
label="物流名称"
style="display: flex;flex:50%"
prop={`platformList.${index}.logisticsName`}
rules={[
{
required: true,
message: '请输入物流名称',
trigger: 'blur',
},
]}
>
<el-select
v-model={item.logisticsName}
placeholder="请选择物流名称"
>
{tiktokCarriers.value?.map((el) => (
<el-option
label={el.name}
value={el.name}
key={el.id}
></el-option>
))}{' '}
</el-select>
</el-form-item>
) : (
<el-form-item
key={index}
class="renderItem"
label="物流名称"
style="display: flex;flex:50%"
prop={`platformList.${index}.logisticsName`}
rules={[
{
required: true,
message: '请输入物流名称',
trigger: 'blur',
},
]}
>
<el-input
v-model={item.logisticsName}
placeholder="请输入物流名称"
/>
</el-form-item>
)}
<div style="display: flex;flex:17%">
{(formData?.platformList as platformObj[])?.length - 1 ===
index && (
......@@ -575,6 +607,7 @@ const tableConfig = ref<TableColumn[]>([
onMounted(() => {
getAllList()
getTiktokCarriers()
})
/**
......@@ -835,6 +868,15 @@ async function getAllList() {
}
}
const tiktokCarriers = ref<{ name: string; id: number }[]>([])
/**
* @description: 获取tictok物流承运商
*/
async function getTiktokCarriers() {
const { data } = await getTiktokCarrier()
tiktokCarriers.value = data
}
/**
* @description: 日志弹窗
*/
......
......@@ -641,7 +641,9 @@ const getOrderByIdApi = async (type: string) => {
}
const tempChinaLogs = ref<LogListData[]>([])
const zoneType = ref<string>('Asia/Shanghai')
function changeChinaTime(zone: string) {
zoneType.value = zone
logList.value = tempChinaLogs.value.map((el) => {
return {
...el,
......@@ -1033,24 +1035,28 @@ onMounted(() => {
<el-tab-pane label="操作日志" @tab-click="operationLog">
<div>
<el-button
type="primary"
:type="zoneType === 'Asia/Shanghai' ? 'primary' : ''"
size="small"
link
style="margin-left: 10px"
@click="changeChinaTime('Asia/Shanghai')"
>转换为中国时间</el-button
>北京时间</el-button
>
<el-button
type="primary"
:type="zoneType === 'America/New_York' ? 'primary' : ''"
size="small"
link
style="margin-left: 10px"
@click="changeChinaTime('America/New_York')"
>转换为新泽西时间</el-button
>新泽西时间</el-button
>
<el-button
type="primary"
:type="zoneType === 'America/Los_Angeles' ? 'primary' : ''"
size="small"
link
style="margin-left: 10px"
@click="changeChinaTime('America/Los_Angeles')"
>转换为洛杉矶时间</el-button
>洛杉矶时间</el-button
>
</div>
......
......@@ -50,7 +50,7 @@
v-model="searchForm.craftCode"
clearable
filterable
placeholder="请输入工艺"
placeholder="请选择工艺"
style="width: 150px"
>
<el-option
......@@ -1113,7 +1113,6 @@
</div>
<div
v-if="
row.productionClient === 'JOMALL' &&
row.status !== 'TO_BE_CONFIRMED'
"
class="order-detail-item"
......@@ -1126,21 +1125,6 @@
{{ row.warehouseName }}
</span>
</div>
<div
v-if="
row.productionClient === 'JOMALL' &&
row.status !== 'TO_BE_CONFIRMED'
"
class="order-detail-item"
>
<span class="order-detail-item-label">物流方式:</span>
<span
class="order-detail-item-value"
:title="row.logisticsWayName"
>
{{ row.logisticsWayName }}
</span>
</div>
<div class="order-detail-item">
<span class="order-detail-item-label">收货人:</span>
<span class="order-detail-item-value" :title="row.receiverName">
......@@ -1857,7 +1841,7 @@
v-model="confirmManuShow"
:close-on-click-modal="false"
title="确认生产"
width="40%"
width="500px"
>
<el-form
ref="confirmFormRef"
......@@ -1865,12 +1849,12 @@
label-width="120px"
:rules="confirmRules"
>
<el-form-item label="仓库" prop="warehouseId">
<el-form-item label="发货仓库" prop="warehouseId">
<ElSelect
v-model="confirmForm.warehouseId"
clearable
filterable
placeholder="请选择仓库"
placeholder="请选择发货仓库"
style="width: 80%"
>
<el-option
......@@ -3215,7 +3199,7 @@ const confirmRules = reactive({
warehouseId: [
{
required: true,
message: '请选择仓库',
message: '请选择发货仓库',
trigger: 'change',
},
],
......
......@@ -552,28 +552,6 @@ const trackCodeInput = async () => {
removeFromHistory()
return ElMessage.error('生产单不存在')
}
if (res.data.interceptStatus == 0 || res.data.interceptStatus == 2) {
try {
await ElMessageBox.confirm(
'该生产单已提交至拦截申请,请确认是否继续生产',
'提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
},
)
} catch (error) {
TrackingNumber.value = ''
detail.value = {
id: -1,
podJomallOrderUsId: -1,
imgList: [],
}
trackingNumberRef.value && trackingNumberRef.value.focus()
return
}
}
const d = JSON.parse(JSON.stringify(res.data))
if (d.note) {
......
......@@ -37,6 +37,7 @@
</ElSelect>
</div>
<div class="form-item">
<ElSelect
v-model="warehouseId"
placeholder="请选择仓库"
......@@ -368,6 +369,10 @@ watch(visible, async (value: boolean) => {
_warehouseId.value = locaclWarehouseId
? JSON.parse(locaclWarehouseId)
: props.warehouseList[0].id
_warehouseId.value = locaclWarehouseId
? JSON.parse(locaclWarehouseId)
: props.warehouseList[0].id
if (userStore.user?.factory.id) {
try {
await socket.init(
......
......@@ -2,7 +2,7 @@
<el-dialog
title="处理结果"
v-model="resultDialog"
width="600px"
width="1200px"
:close-on-click-modal="false"
@closed="closedFn"
>
......@@ -33,8 +33,17 @@
<div style="margin: 15px 0"></div>
<el-checkbox-group v-model="selectedList" @change="checkChange">
<div style="display: block" v-for="(item, index) in list" :key="index">
<el-checkbox :value="item">
{{ '工厂订单号:' + item.factoryOrderNumber + ' ' + item.message }}
<span
style="
display: inline-block;
width: 100%;
white-space: wrap;
line-height: 22px;
"
> <span>订单号:{{item.factoryOrderNumber}},</span>{{ item.message }}</span
>
</el-checkbox>
</div>
</el-checkbox-group>
......
<script setup lang="ts">
import { defineModel } from 'vue'
import { updateAddressApi } from '@/api/podUsOrder.ts'
import {AddressInfo} from '@/types/api/podUsOrder.ts'
import { AddressInfo } from '@/types/api/podUsOrder.ts'
const emits = defineEmits(['success'])
defineProps<{
......@@ -117,6 +117,8 @@ const submitForm = async () => {
v-model="form.receiverAddress1"
clearable
placeholder="请输入地址1"
maxlength="50"
show-word-limit
/>
</el-form-item>
<el-form-item label="地址2" prop="receiverAddress2">
......@@ -124,6 +126,8 @@ const submitForm = async () => {
v-model="form.receiverAddress2"
clearable
placeholder="请输入地址2"
maxlength="50"
show-word-limit
/>
</el-form-item>
<el-form-item label="邮政编码" prop="receiverPostCode">
......
<script setup lang="ts">
import { reactive, ref } from 'vue'
import cardWrapper from './cardWrapper.vue'
const queryParams = reactive({
name: "",
sku: "",
diy_sku: "",
print_type: "",
category_id: "",
});
const pager = reactive({
page:1,
size:100,
loading: false ,
count: 0,
lists: [] ,
extend: {}
})
const setCurrentImg = (item: any, val: string) => {
item.img_url = val;
};
const categoryTree = ref([])
const resetPage = () => {
}
</script>
<template>
<div class="product">
<el-card>
<el-form
ref="formRef"
class="searchForm"
label-width="80px"
:model="queryParams"
:inline="true"
>
<el-form-item label="商品名称">
<el-input
v-model="queryParams.name"
clearable
maxlength="40"
style="width: 150px"
show-word-limit
placeholder="请输入商品名称"
/>
</el-form-item>
<el-form-item label="SKU">
<el-input
v-model="queryParams.sku"
clearable
style="width: 150px"
placeholder="请输入sku"
/>
</el-form-item>
<el-form-item label="印花类型">
<el-select
v-model="queryParams.print_type"
style="width: 150px"
clearable
placeholder="请选择"
>
<el-option
v-for="(item, index) in ['满印', '局部印']"
:key="index"
:label="item"
:value="index"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="商品分类">
<el-cascader
ref="categoryCascader"
v-model="queryParams.category_id"
:options="categoryTree"
clearable
style="width: 150px"
:props="{
label: 'name',
value: 'id',
emitPath: false,
}"
:show-all-levels="false"
></el-cascader>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="resetPage">查询</el-button>
</el-form-item>
</el-form>
</el-card>
<div class="product-list">
<el-card
style="flex: 1; flex-shrink: 0; overflow: hidden"
class="!border-none"
shadow="never"
>
<div
v-loading="pager.loading"
class="eltable"
element-loading-text="加载中..."
>
<div v-if="pager.lists.length > 0" id="shopline" class="card-mode">
<div
v-for="(item, index) in pager.lists"
:key="index"
class="card-item"
>
<card-wrapper
:data="item"
:index="index"
is-show-home-sku="bottom"
:is-sku-image-list="true"
:has-width="true"
:is-show-sku="false"
:is-show-sales="false"
:is-custom="true"
@set-current-img="(val) => setCurrentImg(item, val)"
>
<template #operations>
<!-- <img-->
<!-- title="操作日志"-->
<!-- width="24"-->
<!-- height="24"-->
<!-- src="@/assets/images/log.png"-->
<!-- alt=""-->
<!-- @click.stop="viewTheLog(item.id)"-->
<!-- />-->
<img
title="编辑"
width="24"
height="24"
src="@/assets/images/edit.png"
alt=""
@click.stop="editInfo(item, 'edit')"
/>
</template>
<template #price>
<span
style="margin: 0 5px"
class="price"
:title="'建议零售价' + item.sales_price"
>
{{ item.sales_price ? "¥" : ""
}}{{ item.sales_price }}&nbsp;
</span>
</template>
<template #level-time>
<div
class="create-time"
:title="`上架时间:${item.create_time}`"
>
<span>{{ item.create_time }}</span>
</div>
</template>
<template #synthesizeStatus>
<div title="印花状态" style="position: absolute; right: 0">
<el-tag :type="item.print_type == 0 ? '' : 'warning'">
{{ item.print_type == 0 ? "满印" : "局部印" }}
</el-tag>
</div>
</template>
<template #otherContent>
<div class="sds-keyid">
<div class="product-id" @click.stop="copy(item.id)">
<img
:title="'复制' + item.id"
width="20"
src="@/assets/images/id.png"
alt=""
/>
<span :title="item.id">
{{ item.id }}
</span>
</div>
<div class="product-sku" @click.stop="copy(item.sku)">
<span :title="item.sku">
{{ item.sku }}
</span>
</div>
</div>
</template>
</card-wrapper>
</div>
</div>
<div v-else class="empty">暂无数据</div>
</div>
<div class="flex justify-center mt-4">
<div
style="
display: flex;
align-items: center;
margin-left: 20px;
width: max-content;
"
>
<span>一行展示</span>
<el-input
v-model="rowNumber"
type="number"
style="width: 80px; margin: 0 10px"
placeholder="请输入"
clearable
@change="changeRowNumber"
/>
<span>条</span>
</div>
&emsp;&emsp;&emsp;
<pagination v-model="pager" @change="getLists" />
</div>
</el-card>
</div>
</div>
</template>
<style scoped lang="scss">
.product{
display: flex;
flex-direction: column;
height: 100%;
}
.searchForm{
::v-deep(.el-form-item){
margin-bottom: 0;
}
}
.justify-center{
display: flex;
justify-content: center;
}
.product-list{
flex: 1;
margin-top: 10px;
flex-shrink: 0;
::v-deep(.el-card){
height: 100%;
.el-card__body{
display: flex;
height: 100%;
flex-direction: column;
.eltable{
flex: 1;
flex-shrink: 0;
overflow: auto;
display: flex;
align-items: center;
justify-content: center;
}
}
}
}
</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: 90%" />
</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: 200px;
}
.form {
margin-bottom: 15px;
}
}
</style>
......@@ -22,18 +22,4 @@ export default defineConfig({
resolve: {
alias: { '@': '/src' },
},
server: {
port: 9803,
host: true,
proxy: {
'/api': {
target: 'http://10.168.31.193:8060',
},
'/ws': {
target: 'http://10.168.31.193:8060',
ws: true,
changeOrigin: true,
},
},
},
})
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